diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/device/IrisCameraCapEventHandler.h b/device/IrisCameraCapEventHandler.h index 8b976c5..94f5594 100644 --- a/device/IrisCameraCapEventHandler.h +++ b/device/IrisCameraCapEventHandler.h @@ -1,10 +1,9 @@ -#ifndef IRISCAMERACAPEVENTHANDLER_H +#ifndef IRISCAMERACAPEVENTHANDLER_H #define IRISCAMERACAPEVENTHANDLER_H #include #include -#include "include/opencv2/opencv.hpp" -#include "include/daheng/GalaxyIncludes.h" +#include #include "casic/iris/CasicIrisInterface.h" #include "ProMemory.h" diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/device/IrisCameraCapEventHandler.h b/device/IrisCameraCapEventHandler.h index 8b976c5..94f5594 100644 --- a/device/IrisCameraCapEventHandler.h +++ b/device/IrisCameraCapEventHandler.h @@ -1,10 +1,9 @@ -#ifndef IRISCAMERACAPEVENTHANDLER_H +#ifndef IRISCAMERACAPEVENTHANDLER_H #define IRISCAMERACAPEVENTHANDLER_H #include #include -#include "include/opencv2/opencv.hpp" -#include "include/daheng/GalaxyIncludes.h" +#include #include "casic/iris/CasicIrisInterface.h" #include "ProMemory.h" diff --git a/device/IrisCameraController.cpp b/device/IrisCameraController.cpp index 0928176..4eea013 100644 --- a/device/IrisCameraController.cpp +++ b/device/IrisCameraController.cpp @@ -1,8 +1,8 @@ -#include "IrisCameraController.h" +#include "IrisCameraController.h" IrisCameraController::IrisCameraController(QObject *parent) : QObject(parent) { - this->irisCamHandler = new IrisCameraCapEventHandler(this); + initIrisCameraController(); } IrisCameraController::~IrisCameraController() { @@ -10,101 +10,204 @@ } -void IrisCameraController::initIrisCamera() +void IrisCameraController::initIrisCameraController() { - IGXFactory::GetInstance().Init(); + // Init GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXInitLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraInitError(); + LOG_ERROR("[CameraController]初始化虹膜相机失败"); + return ; + } + LOG_INFO("[CameraController]初始化虹膜相机成功"); //枚举设备 - IGXFactory::GetInstance().UpdateDeviceList(1000, irisCamList); - - this->OpenDevice(); + UpdateDeviceList(); } void IrisCameraController::openIrisCamera() { - //设置Buffer处理模式 - irisStreamFeaturePtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst"); + GX_STATUS emStatus = GX_STATUS_SUCCESS; - //注册回调函数 - irisStreamPtr->RegisterCaptureCallback(irisCamHandler, &irisCamPtr); + if (m_ui32DeviceNum > 0) { + emStatus = GXOpenDeviceByIndex(1, &m_hDevice); - //开启流层通道 - irisStreamPtr->StartGrab(); + if (emStatus == GX_STATUS_SUCCESS) { + LOG_INFO("[CameraController]开启虹膜相机成功"); - //发送开采命令 - irisFeaturePtr->GetCommandFeature("AcquisitionStart")->Execute(); + // isOpen flag set true + m_bOpen = true; - // 启动定时器 - TimeCounterUtil::getInstance().irisCapCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); // 50ms执行一次定时器 + SetUpAcquisitionThread(); + } + } + + return; } void IrisCameraController::closeIrisCamera() { - + // Release GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXCloseLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraTermError(); + } } void IrisCameraController::startCapture() { // 获取定时器, 绑定定时函数 - connect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString()); + bool bSetDone = false; + // Set acquisition buffer number + bSetDone = SetAcquisitionBufferNum(); + if (!bSetDone) + { + return; + } + + bool bPrepareDone = false; + // Alloc resource for image acquisition + bPrepareDone = m_pobjAcqThread->PrepareForShowImg(); + if (!bPrepareDone) + { + return; + } + + // Device start acquisition and start acquisition thread + StartAcquisition(); + + LOG_DEBUG(QString("[CameraController][startCapture]虹膜相机拍图").toStdString()); + + // Do not start timer when acquisition start failed + if (!m_bAcquisitionStart) + { + return; + } } void IrisCameraController::stopCapture() { - // 获取定时器, 绑定定时函数 - disconnect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString()); - + this->StopAcquisition(); } -void IrisCameraController::getOneFaceFrm() +void IrisCameraController::SetUpAcquisitionThread() { - // 发送软触发命令(在触发模式开启时有效) - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::getLeftAndRightEyeFrame() -{ - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::OpenDevice() -{ - auto device = irisCamList.at(0); - - irisCamPtr = IGXFactory::GetInstance().OpenDeviceByUserID(device.GetUserID(), GX_ACCESS_EXCLUSIVE); - irisFeaturePtr = irisCamPtr->GetRemoteFeatureControl(); - - // 判断设备流是否大于零, 如果大于零则打开流 - int nStreamCount = irisCamPtr->GetStreamCount(); - if (nStreamCount > 0) + // if Acquisition thread is on Stop acquisition thread + if (m_pobjAcqThread != NULL) { - irisStreamPtr = irisCamPtr->OpenStream(0); - irisStreamFeaturePtr = irisStreamPtr->GetFeatureControl(); + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Release acquisition thread object + RELEASE_ALLOC_MEM(m_pobjAcqThread); } - // 建议用户在打开网络相机之后, 根据当前网络环境设置相机的流通道包长值, - // 以提高网络相机的采集性能, 设置方法参考以下代码。 - GX_DEVICE_CLASS_LIST objDeviceClass = irisCamPtr->GetDeviceInfo().GetDeviceClass(); - if(GX_DEVICE_CLASS_GEV == objDeviceClass) + // Instantiation acquisition thread + try { - // 判断设备是否支持流通道数据包功能 - if(true == irisFeaturePtr->IsImplemented("GevSCPSPacketSize")) - { - // 获取当前网络环境的最优包长值 - int nPacketSize = irisStreamPtr->GetOptimalPacketSize(); - // 将最优包长值设置为当前设备的流通道包长值 - irisFeaturePtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize); - } + m_pobjAcqThread = new CAcquisitionThread(); + m_pobjAcqThread->m_hDevice = m_hDevice; + } + catch (std::bad_alloc &e) + { + QMessageBox::about(NULL, "Allocate memory error", "Cannot allocate memory, please exit this app!"); + RELEASE_ALLOC_MEM(m_pobjAcqThread); + return; } - //设置采集模式为连续采集模式 - irisFeaturePtr->GetEnumFeature("AcquisitionMode")->SetValue("Continuous"); + return; +} - //设置触发模式关 - irisFeaturePtr->GetEnumFeature("TriggerMode")->SetValue("On"); - irisFeaturePtr->GetEnumFeature("TriggerSource")->SetValue("Software"); +void IrisCameraController::UpdateDeviceList() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Enumerate Devcie List + emStatus = GXUpdateDeviceList(&m_ui32DeviceNum, ENUMRATE_TIME_OUT); + + LOG_INFO(QString("[CameraController]枚举虹膜相机成功[%1]").arg(m_ui32DeviceNum).toStdString()); + + return; +} + +void IrisCameraController::StartAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + emStatus = GXStreamOn(m_hDevice); + + // Set acquisition thread run flag + m_pobjAcqThread->m_bAcquisitionThreadFlag = true; + + // Acquisition thread start + m_pobjAcqThread->start(); + + // isStart flag set true + m_bAcquisitionStart = true; + + return; +} + +void IrisCameraController::StopAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Turn off stream + emStatus = GXStreamOff(m_hDevice); + + // isStart flag set false + m_bAcquisitionStart = false; + + return; +} + +bool IrisCameraController::SetAcquisitionBufferNum() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + uint64_t ui64BufferNum = 0; + int64_t i64PayloadSize = 0; + + // Get device current payload size + emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &i64PayloadSize); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Set buffer quantity of acquisition queue + if (i64PayloadSize == 0) + { + return false; + } + + // Calculate a reasonable number of Buffers for different payload size + // Small ROI and high frame rate will requires more acquisition Buffer + const size_t MAX_MEMORY_SIZE = 8 * 1024 * 1024; // The maximum number of memory bytes available for allocating frame Buffer + const size_t MIN_BUFFER_NUM = 5; // Minimum frame Buffer number + const size_t MAX_BUFFER_NUM = 450; // Maximum frame Buffer number + ui64BufferNum = MAX_MEMORY_SIZE / i64PayloadSize; + ui64BufferNum = (ui64BufferNum <= MIN_BUFFER_NUM) ? MIN_BUFFER_NUM : ui64BufferNum; + ui64BufferNum = (ui64BufferNum >= MAX_BUFFER_NUM) ? MAX_BUFFER_NUM : ui64BufferNum; + + emStatus = GXSetAcqusitionBufferNumber(m_hDevice, ui64BufferNum); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Transfer buffer number to acquisition thread class for using GXDQAllBufs + m_pobjAcqThread->m_ui64AcquisitionBufferNum = ui64BufferNum; + + return true; } diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/device/IrisCameraCapEventHandler.h b/device/IrisCameraCapEventHandler.h index 8b976c5..94f5594 100644 --- a/device/IrisCameraCapEventHandler.h +++ b/device/IrisCameraCapEventHandler.h @@ -1,10 +1,9 @@ -#ifndef IRISCAMERACAPEVENTHANDLER_H +#ifndef IRISCAMERACAPEVENTHANDLER_H #define IRISCAMERACAPEVENTHANDLER_H #include #include -#include "include/opencv2/opencv.hpp" -#include "include/daheng/GalaxyIncludes.h" +#include #include "casic/iris/CasicIrisInterface.h" #include "ProMemory.h" diff --git a/device/IrisCameraController.cpp b/device/IrisCameraController.cpp index 0928176..4eea013 100644 --- a/device/IrisCameraController.cpp +++ b/device/IrisCameraController.cpp @@ -1,8 +1,8 @@ -#include "IrisCameraController.h" +#include "IrisCameraController.h" IrisCameraController::IrisCameraController(QObject *parent) : QObject(parent) { - this->irisCamHandler = new IrisCameraCapEventHandler(this); + initIrisCameraController(); } IrisCameraController::~IrisCameraController() { @@ -10,101 +10,204 @@ } -void IrisCameraController::initIrisCamera() +void IrisCameraController::initIrisCameraController() { - IGXFactory::GetInstance().Init(); + // Init GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXInitLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraInitError(); + LOG_ERROR("[CameraController]初始化虹膜相机失败"); + return ; + } + LOG_INFO("[CameraController]初始化虹膜相机成功"); //枚举设备 - IGXFactory::GetInstance().UpdateDeviceList(1000, irisCamList); - - this->OpenDevice(); + UpdateDeviceList(); } void IrisCameraController::openIrisCamera() { - //设置Buffer处理模式 - irisStreamFeaturePtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst"); + GX_STATUS emStatus = GX_STATUS_SUCCESS; - //注册回调函数 - irisStreamPtr->RegisterCaptureCallback(irisCamHandler, &irisCamPtr); + if (m_ui32DeviceNum > 0) { + emStatus = GXOpenDeviceByIndex(1, &m_hDevice); - //开启流层通道 - irisStreamPtr->StartGrab(); + if (emStatus == GX_STATUS_SUCCESS) { + LOG_INFO("[CameraController]开启虹膜相机成功"); - //发送开采命令 - irisFeaturePtr->GetCommandFeature("AcquisitionStart")->Execute(); + // isOpen flag set true + m_bOpen = true; - // 启动定时器 - TimeCounterUtil::getInstance().irisCapCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); // 50ms执行一次定时器 + SetUpAcquisitionThread(); + } + } + + return; } void IrisCameraController::closeIrisCamera() { - + // Release GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXCloseLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraTermError(); + } } void IrisCameraController::startCapture() { // 获取定时器, 绑定定时函数 - connect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString()); + bool bSetDone = false; + // Set acquisition buffer number + bSetDone = SetAcquisitionBufferNum(); + if (!bSetDone) + { + return; + } + + bool bPrepareDone = false; + // Alloc resource for image acquisition + bPrepareDone = m_pobjAcqThread->PrepareForShowImg(); + if (!bPrepareDone) + { + return; + } + + // Device start acquisition and start acquisition thread + StartAcquisition(); + + LOG_DEBUG(QString("[CameraController][startCapture]虹膜相机拍图").toStdString()); + + // Do not start timer when acquisition start failed + if (!m_bAcquisitionStart) + { + return; + } } void IrisCameraController::stopCapture() { - // 获取定时器, 绑定定时函数 - disconnect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString()); - + this->StopAcquisition(); } -void IrisCameraController::getOneFaceFrm() +void IrisCameraController::SetUpAcquisitionThread() { - // 发送软触发命令(在触发模式开启时有效) - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::getLeftAndRightEyeFrame() -{ - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::OpenDevice() -{ - auto device = irisCamList.at(0); - - irisCamPtr = IGXFactory::GetInstance().OpenDeviceByUserID(device.GetUserID(), GX_ACCESS_EXCLUSIVE); - irisFeaturePtr = irisCamPtr->GetRemoteFeatureControl(); - - // 判断设备流是否大于零, 如果大于零则打开流 - int nStreamCount = irisCamPtr->GetStreamCount(); - if (nStreamCount > 0) + // if Acquisition thread is on Stop acquisition thread + if (m_pobjAcqThread != NULL) { - irisStreamPtr = irisCamPtr->OpenStream(0); - irisStreamFeaturePtr = irisStreamPtr->GetFeatureControl(); + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Release acquisition thread object + RELEASE_ALLOC_MEM(m_pobjAcqThread); } - // 建议用户在打开网络相机之后, 根据当前网络环境设置相机的流通道包长值, - // 以提高网络相机的采集性能, 设置方法参考以下代码。 - GX_DEVICE_CLASS_LIST objDeviceClass = irisCamPtr->GetDeviceInfo().GetDeviceClass(); - if(GX_DEVICE_CLASS_GEV == objDeviceClass) + // Instantiation acquisition thread + try { - // 判断设备是否支持流通道数据包功能 - if(true == irisFeaturePtr->IsImplemented("GevSCPSPacketSize")) - { - // 获取当前网络环境的最优包长值 - int nPacketSize = irisStreamPtr->GetOptimalPacketSize(); - // 将最优包长值设置为当前设备的流通道包长值 - irisFeaturePtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize); - } + m_pobjAcqThread = new CAcquisitionThread(); + m_pobjAcqThread->m_hDevice = m_hDevice; + } + catch (std::bad_alloc &e) + { + QMessageBox::about(NULL, "Allocate memory error", "Cannot allocate memory, please exit this app!"); + RELEASE_ALLOC_MEM(m_pobjAcqThread); + return; } - //设置采集模式为连续采集模式 - irisFeaturePtr->GetEnumFeature("AcquisitionMode")->SetValue("Continuous"); + return; +} - //设置触发模式关 - irisFeaturePtr->GetEnumFeature("TriggerMode")->SetValue("On"); - irisFeaturePtr->GetEnumFeature("TriggerSource")->SetValue("Software"); +void IrisCameraController::UpdateDeviceList() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Enumerate Devcie List + emStatus = GXUpdateDeviceList(&m_ui32DeviceNum, ENUMRATE_TIME_OUT); + + LOG_INFO(QString("[CameraController]枚举虹膜相机成功[%1]").arg(m_ui32DeviceNum).toStdString()); + + return; +} + +void IrisCameraController::StartAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + emStatus = GXStreamOn(m_hDevice); + + // Set acquisition thread run flag + m_pobjAcqThread->m_bAcquisitionThreadFlag = true; + + // Acquisition thread start + m_pobjAcqThread->start(); + + // isStart flag set true + m_bAcquisitionStart = true; + + return; +} + +void IrisCameraController::StopAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Turn off stream + emStatus = GXStreamOff(m_hDevice); + + // isStart flag set false + m_bAcquisitionStart = false; + + return; +} + +bool IrisCameraController::SetAcquisitionBufferNum() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + uint64_t ui64BufferNum = 0; + int64_t i64PayloadSize = 0; + + // Get device current payload size + emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &i64PayloadSize); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Set buffer quantity of acquisition queue + if (i64PayloadSize == 0) + { + return false; + } + + // Calculate a reasonable number of Buffers for different payload size + // Small ROI and high frame rate will requires more acquisition Buffer + const size_t MAX_MEMORY_SIZE = 8 * 1024 * 1024; // The maximum number of memory bytes available for allocating frame Buffer + const size_t MIN_BUFFER_NUM = 5; // Minimum frame Buffer number + const size_t MAX_BUFFER_NUM = 450; // Maximum frame Buffer number + ui64BufferNum = MAX_MEMORY_SIZE / i64PayloadSize; + ui64BufferNum = (ui64BufferNum <= MIN_BUFFER_NUM) ? MIN_BUFFER_NUM : ui64BufferNum; + ui64BufferNum = (ui64BufferNum >= MAX_BUFFER_NUM) ? MAX_BUFFER_NUM : ui64BufferNum; + + emStatus = GXSetAcqusitionBufferNumber(m_hDevice, ui64BufferNum); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Transfer buffer number to acquisition thread class for using GXDQAllBufs + m_pobjAcqThread->m_ui64AcquisitionBufferNum = ui64BufferNum; + + return true; } diff --git a/device/IrisCameraController.h b/device/IrisCameraController.h index 5d7e269..67cbe2f 100644 --- a/device/IrisCameraController.h +++ b/device/IrisCameraController.h @@ -1,11 +1,12 @@ -#ifndef IRISCAMERACONTROLLER_H +#ifndef IRISCAMERACONTROLLER_H #define IRISCAMERACONTROLLER_H #include -#include "IrisCameraCapEventHandler.h" +#include "AcquisitionThread.h" +#include "utils/UtilInclude.h" -class IrisCameraCapEventHandler; +#define ENUMRATE_TIME_OUT 200 class IrisCameraController : public QObject { @@ -14,36 +15,31 @@ explicit IrisCameraController(QObject *parent = nullptr); ~IrisCameraController(); - // 初始化并打开人脸相机 - void initIrisCamera(); void openIrisCamera(); void closeIrisCamera(); void startCapture(); void stopCapture(); - void getLeftAndRightEyeFrame(); + CAcquisitionThread * m_pobjAcqThread; + GX_DEV_HANDLE m_hDevice; ///< Device Handle + uint32_t m_ui32DeviceNum; ///< Device number enumerated - IrisCameraCapEventHandler * irisCamHandler; + bool m_bOpen; ///< Flag : camera is opened or not + bool m_bAcquisitionStart; ///< Flag : camera is acquiring or not private: - GxIAPICPP::gxdeviceinfo_vector irisCamList; - - CGXDevicePointer irisCamPtr; ///< 设备句柄 - - CGXStreamPointer irisStreamPtr; ///< 左眼设备流 - - CGXFeatureControlPointer irisFeaturePtr; ///< 左眼属性控制器 - - CGXFeatureControlPointer irisStreamFeaturePtr; ///< 左眼流层控制器对象 - - void OpenDevice(); + // 初始化并打开人脸相机 + void initIrisCameraController(); + void SetUpAcquisitionThread(); + void UpdateDeviceList(); + bool SetAcquisitionBufferNum(); + void StartAcquisition(); + void StopAcquisition(); signals: - -public slots: - void getOneFaceFrm(); - + void irisCameraInitError(); + void irisCameraTermError(); }; #endif // IRISCAMERACONTROLLER_H diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/device/IrisCameraCapEventHandler.h b/device/IrisCameraCapEventHandler.h index 8b976c5..94f5594 100644 --- a/device/IrisCameraCapEventHandler.h +++ b/device/IrisCameraCapEventHandler.h @@ -1,10 +1,9 @@ -#ifndef IRISCAMERACAPEVENTHANDLER_H +#ifndef IRISCAMERACAPEVENTHANDLER_H #define IRISCAMERACAPEVENTHANDLER_H #include #include -#include "include/opencv2/opencv.hpp" -#include "include/daheng/GalaxyIncludes.h" +#include #include "casic/iris/CasicIrisInterface.h" #include "ProMemory.h" diff --git a/device/IrisCameraController.cpp b/device/IrisCameraController.cpp index 0928176..4eea013 100644 --- a/device/IrisCameraController.cpp +++ b/device/IrisCameraController.cpp @@ -1,8 +1,8 @@ -#include "IrisCameraController.h" +#include "IrisCameraController.h" IrisCameraController::IrisCameraController(QObject *parent) : QObject(parent) { - this->irisCamHandler = new IrisCameraCapEventHandler(this); + initIrisCameraController(); } IrisCameraController::~IrisCameraController() { @@ -10,101 +10,204 @@ } -void IrisCameraController::initIrisCamera() +void IrisCameraController::initIrisCameraController() { - IGXFactory::GetInstance().Init(); + // Init GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXInitLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraInitError(); + LOG_ERROR("[CameraController]初始化虹膜相机失败"); + return ; + } + LOG_INFO("[CameraController]初始化虹膜相机成功"); //枚举设备 - IGXFactory::GetInstance().UpdateDeviceList(1000, irisCamList); - - this->OpenDevice(); + UpdateDeviceList(); } void IrisCameraController::openIrisCamera() { - //设置Buffer处理模式 - irisStreamFeaturePtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst"); + GX_STATUS emStatus = GX_STATUS_SUCCESS; - //注册回调函数 - irisStreamPtr->RegisterCaptureCallback(irisCamHandler, &irisCamPtr); + if (m_ui32DeviceNum > 0) { + emStatus = GXOpenDeviceByIndex(1, &m_hDevice); - //开启流层通道 - irisStreamPtr->StartGrab(); + if (emStatus == GX_STATUS_SUCCESS) { + LOG_INFO("[CameraController]开启虹膜相机成功"); - //发送开采命令 - irisFeaturePtr->GetCommandFeature("AcquisitionStart")->Execute(); + // isOpen flag set true + m_bOpen = true; - // 启动定时器 - TimeCounterUtil::getInstance().irisCapCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); // 50ms执行一次定时器 + SetUpAcquisitionThread(); + } + } + + return; } void IrisCameraController::closeIrisCamera() { - + // Release GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXCloseLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraTermError(); + } } void IrisCameraController::startCapture() { // 获取定时器, 绑定定时函数 - connect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString()); + bool bSetDone = false; + // Set acquisition buffer number + bSetDone = SetAcquisitionBufferNum(); + if (!bSetDone) + { + return; + } + + bool bPrepareDone = false; + // Alloc resource for image acquisition + bPrepareDone = m_pobjAcqThread->PrepareForShowImg(); + if (!bPrepareDone) + { + return; + } + + // Device start acquisition and start acquisition thread + StartAcquisition(); + + LOG_DEBUG(QString("[CameraController][startCapture]虹膜相机拍图").toStdString()); + + // Do not start timer when acquisition start failed + if (!m_bAcquisitionStart) + { + return; + } } void IrisCameraController::stopCapture() { - // 获取定时器, 绑定定时函数 - disconnect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString()); - + this->StopAcquisition(); } -void IrisCameraController::getOneFaceFrm() +void IrisCameraController::SetUpAcquisitionThread() { - // 发送软触发命令(在触发模式开启时有效) - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::getLeftAndRightEyeFrame() -{ - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::OpenDevice() -{ - auto device = irisCamList.at(0); - - irisCamPtr = IGXFactory::GetInstance().OpenDeviceByUserID(device.GetUserID(), GX_ACCESS_EXCLUSIVE); - irisFeaturePtr = irisCamPtr->GetRemoteFeatureControl(); - - // 判断设备流是否大于零, 如果大于零则打开流 - int nStreamCount = irisCamPtr->GetStreamCount(); - if (nStreamCount > 0) + // if Acquisition thread is on Stop acquisition thread + if (m_pobjAcqThread != NULL) { - irisStreamPtr = irisCamPtr->OpenStream(0); - irisStreamFeaturePtr = irisStreamPtr->GetFeatureControl(); + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Release acquisition thread object + RELEASE_ALLOC_MEM(m_pobjAcqThread); } - // 建议用户在打开网络相机之后, 根据当前网络环境设置相机的流通道包长值, - // 以提高网络相机的采集性能, 设置方法参考以下代码。 - GX_DEVICE_CLASS_LIST objDeviceClass = irisCamPtr->GetDeviceInfo().GetDeviceClass(); - if(GX_DEVICE_CLASS_GEV == objDeviceClass) + // Instantiation acquisition thread + try { - // 判断设备是否支持流通道数据包功能 - if(true == irisFeaturePtr->IsImplemented("GevSCPSPacketSize")) - { - // 获取当前网络环境的最优包长值 - int nPacketSize = irisStreamPtr->GetOptimalPacketSize(); - // 将最优包长值设置为当前设备的流通道包长值 - irisFeaturePtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize); - } + m_pobjAcqThread = new CAcquisitionThread(); + m_pobjAcqThread->m_hDevice = m_hDevice; + } + catch (std::bad_alloc &e) + { + QMessageBox::about(NULL, "Allocate memory error", "Cannot allocate memory, please exit this app!"); + RELEASE_ALLOC_MEM(m_pobjAcqThread); + return; } - //设置采集模式为连续采集模式 - irisFeaturePtr->GetEnumFeature("AcquisitionMode")->SetValue("Continuous"); + return; +} - //设置触发模式关 - irisFeaturePtr->GetEnumFeature("TriggerMode")->SetValue("On"); - irisFeaturePtr->GetEnumFeature("TriggerSource")->SetValue("Software"); +void IrisCameraController::UpdateDeviceList() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Enumerate Devcie List + emStatus = GXUpdateDeviceList(&m_ui32DeviceNum, ENUMRATE_TIME_OUT); + + LOG_INFO(QString("[CameraController]枚举虹膜相机成功[%1]").arg(m_ui32DeviceNum).toStdString()); + + return; +} + +void IrisCameraController::StartAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + emStatus = GXStreamOn(m_hDevice); + + // Set acquisition thread run flag + m_pobjAcqThread->m_bAcquisitionThreadFlag = true; + + // Acquisition thread start + m_pobjAcqThread->start(); + + // isStart flag set true + m_bAcquisitionStart = true; + + return; +} + +void IrisCameraController::StopAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Turn off stream + emStatus = GXStreamOff(m_hDevice); + + // isStart flag set false + m_bAcquisitionStart = false; + + return; +} + +bool IrisCameraController::SetAcquisitionBufferNum() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + uint64_t ui64BufferNum = 0; + int64_t i64PayloadSize = 0; + + // Get device current payload size + emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &i64PayloadSize); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Set buffer quantity of acquisition queue + if (i64PayloadSize == 0) + { + return false; + } + + // Calculate a reasonable number of Buffers for different payload size + // Small ROI and high frame rate will requires more acquisition Buffer + const size_t MAX_MEMORY_SIZE = 8 * 1024 * 1024; // The maximum number of memory bytes available for allocating frame Buffer + const size_t MIN_BUFFER_NUM = 5; // Minimum frame Buffer number + const size_t MAX_BUFFER_NUM = 450; // Maximum frame Buffer number + ui64BufferNum = MAX_MEMORY_SIZE / i64PayloadSize; + ui64BufferNum = (ui64BufferNum <= MIN_BUFFER_NUM) ? MIN_BUFFER_NUM : ui64BufferNum; + ui64BufferNum = (ui64BufferNum >= MAX_BUFFER_NUM) ? MAX_BUFFER_NUM : ui64BufferNum; + + emStatus = GXSetAcqusitionBufferNumber(m_hDevice, ui64BufferNum); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Transfer buffer number to acquisition thread class for using GXDQAllBufs + m_pobjAcqThread->m_ui64AcquisitionBufferNum = ui64BufferNum; + + return true; } diff --git a/device/IrisCameraController.h b/device/IrisCameraController.h index 5d7e269..67cbe2f 100644 --- a/device/IrisCameraController.h +++ b/device/IrisCameraController.h @@ -1,11 +1,12 @@ -#ifndef IRISCAMERACONTROLLER_H +#ifndef IRISCAMERACONTROLLER_H #define IRISCAMERACONTROLLER_H #include -#include "IrisCameraCapEventHandler.h" +#include "AcquisitionThread.h" +#include "utils/UtilInclude.h" -class IrisCameraCapEventHandler; +#define ENUMRATE_TIME_OUT 200 class IrisCameraController : public QObject { @@ -14,36 +15,31 @@ explicit IrisCameraController(QObject *parent = nullptr); ~IrisCameraController(); - // 初始化并打开人脸相机 - void initIrisCamera(); void openIrisCamera(); void closeIrisCamera(); void startCapture(); void stopCapture(); - void getLeftAndRightEyeFrame(); + CAcquisitionThread * m_pobjAcqThread; + GX_DEV_HANDLE m_hDevice; ///< Device Handle + uint32_t m_ui32DeviceNum; ///< Device number enumerated - IrisCameraCapEventHandler * irisCamHandler; + bool m_bOpen; ///< Flag : camera is opened or not + bool m_bAcquisitionStart; ///< Flag : camera is acquiring or not private: - GxIAPICPP::gxdeviceinfo_vector irisCamList; - - CGXDevicePointer irisCamPtr; ///< 设备句柄 - - CGXStreamPointer irisStreamPtr; ///< 左眼设备流 - - CGXFeatureControlPointer irisFeaturePtr; ///< 左眼属性控制器 - - CGXFeatureControlPointer irisStreamFeaturePtr; ///< 左眼流层控制器对象 - - void OpenDevice(); + // 初始化并打开人脸相机 + void initIrisCameraController(); + void SetUpAcquisitionThread(); + void UpdateDeviceList(); + bool SetAcquisitionBufferNum(); + void StartAcquisition(); + void StopAcquisition(); signals: - -public slots: - void getOneFaceFrm(); - + void irisCameraInitError(); + void irisCameraTermError(); }; #endif // IRISCAMERACONTROLLER_H diff --git a/device/device.pri b/device/device.pri index d1330a0..583721b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,13 +1,14 @@ HEADERS += $$PWD/IrisCameraController.h -HEADERS += $$PWD/IrisCameraCapEventHandler.h -#HEADERS += $$PWD/iris/IrisRegistProcess.h +#HEADERS += $$PWD/IrisCameraCapEventHandler.h +HEADERS += $$PWD/Common.h +HEADERS += $$PWD/AcquisitionThread.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h SOURCES += $$PWD/IrisCameraController.cpp -SOURCES += $$PWD/IrisCameraCapEventHandler.cpp -#SOURCES += $$PWD/iris/IrisRegistProcess.cpp +#SOURCES += $$PWD/IrisCameraCapEventHandler.cpp +SOURCES += $$PWD/AcquisitionThread.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/device/IrisCameraCapEventHandler.h b/device/IrisCameraCapEventHandler.h index 8b976c5..94f5594 100644 --- a/device/IrisCameraCapEventHandler.h +++ b/device/IrisCameraCapEventHandler.h @@ -1,10 +1,9 @@ -#ifndef IRISCAMERACAPEVENTHANDLER_H +#ifndef IRISCAMERACAPEVENTHANDLER_H #define IRISCAMERACAPEVENTHANDLER_H #include #include -#include "include/opencv2/opencv.hpp" -#include "include/daheng/GalaxyIncludes.h" +#include #include "casic/iris/CasicIrisInterface.h" #include "ProMemory.h" diff --git a/device/IrisCameraController.cpp b/device/IrisCameraController.cpp index 0928176..4eea013 100644 --- a/device/IrisCameraController.cpp +++ b/device/IrisCameraController.cpp @@ -1,8 +1,8 @@ -#include "IrisCameraController.h" +#include "IrisCameraController.h" IrisCameraController::IrisCameraController(QObject *parent) : QObject(parent) { - this->irisCamHandler = new IrisCameraCapEventHandler(this); + initIrisCameraController(); } IrisCameraController::~IrisCameraController() { @@ -10,101 +10,204 @@ } -void IrisCameraController::initIrisCamera() +void IrisCameraController::initIrisCameraController() { - IGXFactory::GetInstance().Init(); + // Init GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXInitLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraInitError(); + LOG_ERROR("[CameraController]初始化虹膜相机失败"); + return ; + } + LOG_INFO("[CameraController]初始化虹膜相机成功"); //枚举设备 - IGXFactory::GetInstance().UpdateDeviceList(1000, irisCamList); - - this->OpenDevice(); + UpdateDeviceList(); } void IrisCameraController::openIrisCamera() { - //设置Buffer处理模式 - irisStreamFeaturePtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst"); + GX_STATUS emStatus = GX_STATUS_SUCCESS; - //注册回调函数 - irisStreamPtr->RegisterCaptureCallback(irisCamHandler, &irisCamPtr); + if (m_ui32DeviceNum > 0) { + emStatus = GXOpenDeviceByIndex(1, &m_hDevice); - //开启流层通道 - irisStreamPtr->StartGrab(); + if (emStatus == GX_STATUS_SUCCESS) { + LOG_INFO("[CameraController]开启虹膜相机成功"); - //发送开采命令 - irisFeaturePtr->GetCommandFeature("AcquisitionStart")->Execute(); + // isOpen flag set true + m_bOpen = true; - // 启动定时器 - TimeCounterUtil::getInstance().irisCapCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); // 50ms执行一次定时器 + SetUpAcquisitionThread(); + } + } + + return; } void IrisCameraController::closeIrisCamera() { - + // Release GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXCloseLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraTermError(); + } } void IrisCameraController::startCapture() { // 获取定时器, 绑定定时函数 - connect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString()); + bool bSetDone = false; + // Set acquisition buffer number + bSetDone = SetAcquisitionBufferNum(); + if (!bSetDone) + { + return; + } + + bool bPrepareDone = false; + // Alloc resource for image acquisition + bPrepareDone = m_pobjAcqThread->PrepareForShowImg(); + if (!bPrepareDone) + { + return; + } + + // Device start acquisition and start acquisition thread + StartAcquisition(); + + LOG_DEBUG(QString("[CameraController][startCapture]虹膜相机拍图").toStdString()); + + // Do not start timer when acquisition start failed + if (!m_bAcquisitionStart) + { + return; + } } void IrisCameraController::stopCapture() { - // 获取定时器, 绑定定时函数 - disconnect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString()); - + this->StopAcquisition(); } -void IrisCameraController::getOneFaceFrm() +void IrisCameraController::SetUpAcquisitionThread() { - // 发送软触发命令(在触发模式开启时有效) - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::getLeftAndRightEyeFrame() -{ - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::OpenDevice() -{ - auto device = irisCamList.at(0); - - irisCamPtr = IGXFactory::GetInstance().OpenDeviceByUserID(device.GetUserID(), GX_ACCESS_EXCLUSIVE); - irisFeaturePtr = irisCamPtr->GetRemoteFeatureControl(); - - // 判断设备流是否大于零, 如果大于零则打开流 - int nStreamCount = irisCamPtr->GetStreamCount(); - if (nStreamCount > 0) + // if Acquisition thread is on Stop acquisition thread + if (m_pobjAcqThread != NULL) { - irisStreamPtr = irisCamPtr->OpenStream(0); - irisStreamFeaturePtr = irisStreamPtr->GetFeatureControl(); + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Release acquisition thread object + RELEASE_ALLOC_MEM(m_pobjAcqThread); } - // 建议用户在打开网络相机之后, 根据当前网络环境设置相机的流通道包长值, - // 以提高网络相机的采集性能, 设置方法参考以下代码。 - GX_DEVICE_CLASS_LIST objDeviceClass = irisCamPtr->GetDeviceInfo().GetDeviceClass(); - if(GX_DEVICE_CLASS_GEV == objDeviceClass) + // Instantiation acquisition thread + try { - // 判断设备是否支持流通道数据包功能 - if(true == irisFeaturePtr->IsImplemented("GevSCPSPacketSize")) - { - // 获取当前网络环境的最优包长值 - int nPacketSize = irisStreamPtr->GetOptimalPacketSize(); - // 将最优包长值设置为当前设备的流通道包长值 - irisFeaturePtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize); - } + m_pobjAcqThread = new CAcquisitionThread(); + m_pobjAcqThread->m_hDevice = m_hDevice; + } + catch (std::bad_alloc &e) + { + QMessageBox::about(NULL, "Allocate memory error", "Cannot allocate memory, please exit this app!"); + RELEASE_ALLOC_MEM(m_pobjAcqThread); + return; } - //设置采集模式为连续采集模式 - irisFeaturePtr->GetEnumFeature("AcquisitionMode")->SetValue("Continuous"); + return; +} - //设置触发模式关 - irisFeaturePtr->GetEnumFeature("TriggerMode")->SetValue("On"); - irisFeaturePtr->GetEnumFeature("TriggerSource")->SetValue("Software"); +void IrisCameraController::UpdateDeviceList() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Enumerate Devcie List + emStatus = GXUpdateDeviceList(&m_ui32DeviceNum, ENUMRATE_TIME_OUT); + + LOG_INFO(QString("[CameraController]枚举虹膜相机成功[%1]").arg(m_ui32DeviceNum).toStdString()); + + return; +} + +void IrisCameraController::StartAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + emStatus = GXStreamOn(m_hDevice); + + // Set acquisition thread run flag + m_pobjAcqThread->m_bAcquisitionThreadFlag = true; + + // Acquisition thread start + m_pobjAcqThread->start(); + + // isStart flag set true + m_bAcquisitionStart = true; + + return; +} + +void IrisCameraController::StopAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Turn off stream + emStatus = GXStreamOff(m_hDevice); + + // isStart flag set false + m_bAcquisitionStart = false; + + return; +} + +bool IrisCameraController::SetAcquisitionBufferNum() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + uint64_t ui64BufferNum = 0; + int64_t i64PayloadSize = 0; + + // Get device current payload size + emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &i64PayloadSize); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Set buffer quantity of acquisition queue + if (i64PayloadSize == 0) + { + return false; + } + + // Calculate a reasonable number of Buffers for different payload size + // Small ROI and high frame rate will requires more acquisition Buffer + const size_t MAX_MEMORY_SIZE = 8 * 1024 * 1024; // The maximum number of memory bytes available for allocating frame Buffer + const size_t MIN_BUFFER_NUM = 5; // Minimum frame Buffer number + const size_t MAX_BUFFER_NUM = 450; // Maximum frame Buffer number + ui64BufferNum = MAX_MEMORY_SIZE / i64PayloadSize; + ui64BufferNum = (ui64BufferNum <= MIN_BUFFER_NUM) ? MIN_BUFFER_NUM : ui64BufferNum; + ui64BufferNum = (ui64BufferNum >= MAX_BUFFER_NUM) ? MAX_BUFFER_NUM : ui64BufferNum; + + emStatus = GXSetAcqusitionBufferNumber(m_hDevice, ui64BufferNum); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Transfer buffer number to acquisition thread class for using GXDQAllBufs + m_pobjAcqThread->m_ui64AcquisitionBufferNum = ui64BufferNum; + + return true; } diff --git a/device/IrisCameraController.h b/device/IrisCameraController.h index 5d7e269..67cbe2f 100644 --- a/device/IrisCameraController.h +++ b/device/IrisCameraController.h @@ -1,11 +1,12 @@ -#ifndef IRISCAMERACONTROLLER_H +#ifndef IRISCAMERACONTROLLER_H #define IRISCAMERACONTROLLER_H #include -#include "IrisCameraCapEventHandler.h" +#include "AcquisitionThread.h" +#include "utils/UtilInclude.h" -class IrisCameraCapEventHandler; +#define ENUMRATE_TIME_OUT 200 class IrisCameraController : public QObject { @@ -14,36 +15,31 @@ explicit IrisCameraController(QObject *parent = nullptr); ~IrisCameraController(); - // 初始化并打开人脸相机 - void initIrisCamera(); void openIrisCamera(); void closeIrisCamera(); void startCapture(); void stopCapture(); - void getLeftAndRightEyeFrame(); + CAcquisitionThread * m_pobjAcqThread; + GX_DEV_HANDLE m_hDevice; ///< Device Handle + uint32_t m_ui32DeviceNum; ///< Device number enumerated - IrisCameraCapEventHandler * irisCamHandler; + bool m_bOpen; ///< Flag : camera is opened or not + bool m_bAcquisitionStart; ///< Flag : camera is acquiring or not private: - GxIAPICPP::gxdeviceinfo_vector irisCamList; - - CGXDevicePointer irisCamPtr; ///< 设备句柄 - - CGXStreamPointer irisStreamPtr; ///< 左眼设备流 - - CGXFeatureControlPointer irisFeaturePtr; ///< 左眼属性控制器 - - CGXFeatureControlPointer irisStreamFeaturePtr; ///< 左眼流层控制器对象 - - void OpenDevice(); + // 初始化并打开人脸相机 + void initIrisCameraController(); + void SetUpAcquisitionThread(); + void UpdateDeviceList(); + bool SetAcquisitionBufferNum(); + void StartAcquisition(); + void StopAcquisition(); signals: - -public slots: - void getOneFaceFrm(); - + void irisCameraInitError(); + void irisCameraTermError(); }; #endif // IRISCAMERACONTROLLER_H diff --git a/device/device.pri b/device/device.pri index d1330a0..583721b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,13 +1,14 @@ HEADERS += $$PWD/IrisCameraController.h -HEADERS += $$PWD/IrisCameraCapEventHandler.h -#HEADERS += $$PWD/iris/IrisRegistProcess.h +#HEADERS += $$PWD/IrisCameraCapEventHandler.h +HEADERS += $$PWD/Common.h +HEADERS += $$PWD/AcquisitionThread.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h SOURCES += $$PWD/IrisCameraController.cpp -SOURCES += $$PWD/IrisCameraCapEventHandler.cpp -#SOURCES += $$PWD/iris/IrisRegistProcess.cpp +#SOURCES += $$PWD/IrisCameraCapEventHandler.cpp +SOURCES += $$PWD/AcquisitionThread.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 38f54fe..e4c8a02 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -11,7 +11,7 @@ // 连接算法服务 clientUtil = new SocketClientUtil(this); - clientUtil->connect("192.168.83.223", 50007); + clientUtil->connect(SettingConfig::getInstance().DEBUG_SEGMENT_IP, 50007); // 调用socket发送消息 connect(this, &IrisRecogProcess::sendDataToExract, clientUtil, &SocketClientUtil::sendData); @@ -43,18 +43,18 @@ continue; } - // 1. 图像栈中没有图像则直接返回 - if (ProMemory::getInstance().isIrisQueueEmpty() == true) + // 1. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 + if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) { - qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); + qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } - // 2. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 - if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) + // 2. 图像栈中没有图像则直接返回 + if (ProMemory::getInstance().isIrisQueueEmpty() == true) { - qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); + qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } @@ -73,7 +73,7 @@ int findEyeLast = timer.elapsed(); qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); -// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.matData = cv::imread("/home/casic/code/irisLogs/145333.552.bmp", 0); // irisInfo.hasEye = true; // 4.1 没有找到眼睛则返回 @@ -117,11 +117,10 @@ // 缩放到320 * 240 cv::resize(segMat, segMat, cv::Size(SettingConfig::getInstance().IRIS_WIDTH * 0.5, SettingConfig::getInstance().IRIS_HEIGHT * 0.5)); - - // std::string filename = QString("%1\\%2\\%3-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - // cv::imwrite(filename, segMat); - // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - +/* + std::string filename = QString("%1/%2/%3-seg.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(filename, segMat); +*/ int segMatSize = segMat.cols * segMat.rows; QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 @@ -167,9 +166,9 @@ // 成功接收后清除缓存区 clientUtil->resetRecvBuffer(); /* - std::string pupilSeg = QString("%1\\%2\\%3-pupil-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string maskSeg = QString("%1\\%2\\%3-mask-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string irisSeg = QString("%1\\%2\\%3-iris-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string pupilSeg = QString("%1/%2/%3-pupil-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); cv::imwrite(pupilSeg, pupil); cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); @@ -196,12 +195,20 @@ CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; irisInfo = casic::iris::CasicIrisInterface::getInstance().irisEncode(irisInfo); /* - std::string codeFilename = QString("%1\\%2\\%3-code.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string codeFilename = QString("%1/%2/%3-code.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string maskFilename = QString("%1/%2/%3-mask.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); */ + if (irisInfo.postProcSucc == false) { + qDebug() << "算法post process失败,暂停200ms"; + + addOneTryCount(); + this->msleep(THREAD_MSLEEP); // 200ms后再判断 + continue; + } + // 从编码中提取特征值 irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); @@ -211,6 +218,8 @@ CasicIrisRecState::getInstance().extractTmLast = encodeLast; CasicIrisRecState::getInstance().recogTimeLast += encodeLast; +// cv::imwrite(QString("%1/%2/%3.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(), irisInfo.matData); + // 开始匹配 timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) @@ -219,7 +228,7 @@ float score = casic::iris::CasicIrisInterface::getInstance().calculatePairPoints(feature.irisFeatureCode, irisInfo.irisFeatureCode); // 计算压缩编码的比较值 -// cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); +// cv::imwrite(QString("%1/%2/%3-%4.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; @@ -251,7 +260,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } @@ -268,7 +277,7 @@ CasicIrisRecState::getInstance().tryCount = 0; this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); emit failedMatchedIris(); @@ -290,7 +299,7 @@ // 识别失败时暂停工作 待返回识别界面时再开始工作和拍图 this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); } } else if (ProMemory::getInstance().appState == AppConstants::ApplicationState::STATE_WORKING) @@ -298,7 +307,8 @@ CasicIrisRecState::getInstance().noEyeCount++; // 如果在工作状态 则超过一定次数后返回待机 - if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT) + if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT && + SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT > 0) { // 发送信号待机 emit backToLockScreen(); diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/device/IrisCameraCapEventHandler.h b/device/IrisCameraCapEventHandler.h index 8b976c5..94f5594 100644 --- a/device/IrisCameraCapEventHandler.h +++ b/device/IrisCameraCapEventHandler.h @@ -1,10 +1,9 @@ -#ifndef IRISCAMERACAPEVENTHANDLER_H +#ifndef IRISCAMERACAPEVENTHANDLER_H #define IRISCAMERACAPEVENTHANDLER_H #include #include -#include "include/opencv2/opencv.hpp" -#include "include/daheng/GalaxyIncludes.h" +#include #include "casic/iris/CasicIrisInterface.h" #include "ProMemory.h" diff --git a/device/IrisCameraController.cpp b/device/IrisCameraController.cpp index 0928176..4eea013 100644 --- a/device/IrisCameraController.cpp +++ b/device/IrisCameraController.cpp @@ -1,8 +1,8 @@ -#include "IrisCameraController.h" +#include "IrisCameraController.h" IrisCameraController::IrisCameraController(QObject *parent) : QObject(parent) { - this->irisCamHandler = new IrisCameraCapEventHandler(this); + initIrisCameraController(); } IrisCameraController::~IrisCameraController() { @@ -10,101 +10,204 @@ } -void IrisCameraController::initIrisCamera() +void IrisCameraController::initIrisCameraController() { - IGXFactory::GetInstance().Init(); + // Init GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXInitLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraInitError(); + LOG_ERROR("[CameraController]初始化虹膜相机失败"); + return ; + } + LOG_INFO("[CameraController]初始化虹膜相机成功"); //枚举设备 - IGXFactory::GetInstance().UpdateDeviceList(1000, irisCamList); - - this->OpenDevice(); + UpdateDeviceList(); } void IrisCameraController::openIrisCamera() { - //设置Buffer处理模式 - irisStreamFeaturePtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst"); + GX_STATUS emStatus = GX_STATUS_SUCCESS; - //注册回调函数 - irisStreamPtr->RegisterCaptureCallback(irisCamHandler, &irisCamPtr); + if (m_ui32DeviceNum > 0) { + emStatus = GXOpenDeviceByIndex(1, &m_hDevice); - //开启流层通道 - irisStreamPtr->StartGrab(); + if (emStatus == GX_STATUS_SUCCESS) { + LOG_INFO("[CameraController]开启虹膜相机成功"); - //发送开采命令 - irisFeaturePtr->GetCommandFeature("AcquisitionStart")->Execute(); + // isOpen flag set true + m_bOpen = true; - // 启动定时器 - TimeCounterUtil::getInstance().irisCapCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); // 50ms执行一次定时器 + SetUpAcquisitionThread(); + } + } + + return; } void IrisCameraController::closeIrisCamera() { - + // Release GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXCloseLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraTermError(); + } } void IrisCameraController::startCapture() { // 获取定时器, 绑定定时函数 - connect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString()); + bool bSetDone = false; + // Set acquisition buffer number + bSetDone = SetAcquisitionBufferNum(); + if (!bSetDone) + { + return; + } + + bool bPrepareDone = false; + // Alloc resource for image acquisition + bPrepareDone = m_pobjAcqThread->PrepareForShowImg(); + if (!bPrepareDone) + { + return; + } + + // Device start acquisition and start acquisition thread + StartAcquisition(); + + LOG_DEBUG(QString("[CameraController][startCapture]虹膜相机拍图").toStdString()); + + // Do not start timer when acquisition start failed + if (!m_bAcquisitionStart) + { + return; + } } void IrisCameraController::stopCapture() { - // 获取定时器, 绑定定时函数 - disconnect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString()); - + this->StopAcquisition(); } -void IrisCameraController::getOneFaceFrm() +void IrisCameraController::SetUpAcquisitionThread() { - // 发送软触发命令(在触发模式开启时有效) - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::getLeftAndRightEyeFrame() -{ - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::OpenDevice() -{ - auto device = irisCamList.at(0); - - irisCamPtr = IGXFactory::GetInstance().OpenDeviceByUserID(device.GetUserID(), GX_ACCESS_EXCLUSIVE); - irisFeaturePtr = irisCamPtr->GetRemoteFeatureControl(); - - // 判断设备流是否大于零, 如果大于零则打开流 - int nStreamCount = irisCamPtr->GetStreamCount(); - if (nStreamCount > 0) + // if Acquisition thread is on Stop acquisition thread + if (m_pobjAcqThread != NULL) { - irisStreamPtr = irisCamPtr->OpenStream(0); - irisStreamFeaturePtr = irisStreamPtr->GetFeatureControl(); + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Release acquisition thread object + RELEASE_ALLOC_MEM(m_pobjAcqThread); } - // 建议用户在打开网络相机之后, 根据当前网络环境设置相机的流通道包长值, - // 以提高网络相机的采集性能, 设置方法参考以下代码。 - GX_DEVICE_CLASS_LIST objDeviceClass = irisCamPtr->GetDeviceInfo().GetDeviceClass(); - if(GX_DEVICE_CLASS_GEV == objDeviceClass) + // Instantiation acquisition thread + try { - // 判断设备是否支持流通道数据包功能 - if(true == irisFeaturePtr->IsImplemented("GevSCPSPacketSize")) - { - // 获取当前网络环境的最优包长值 - int nPacketSize = irisStreamPtr->GetOptimalPacketSize(); - // 将最优包长值设置为当前设备的流通道包长值 - irisFeaturePtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize); - } + m_pobjAcqThread = new CAcquisitionThread(); + m_pobjAcqThread->m_hDevice = m_hDevice; + } + catch (std::bad_alloc &e) + { + QMessageBox::about(NULL, "Allocate memory error", "Cannot allocate memory, please exit this app!"); + RELEASE_ALLOC_MEM(m_pobjAcqThread); + return; } - //设置采集模式为连续采集模式 - irisFeaturePtr->GetEnumFeature("AcquisitionMode")->SetValue("Continuous"); + return; +} - //设置触发模式关 - irisFeaturePtr->GetEnumFeature("TriggerMode")->SetValue("On"); - irisFeaturePtr->GetEnumFeature("TriggerSource")->SetValue("Software"); +void IrisCameraController::UpdateDeviceList() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Enumerate Devcie List + emStatus = GXUpdateDeviceList(&m_ui32DeviceNum, ENUMRATE_TIME_OUT); + + LOG_INFO(QString("[CameraController]枚举虹膜相机成功[%1]").arg(m_ui32DeviceNum).toStdString()); + + return; +} + +void IrisCameraController::StartAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + emStatus = GXStreamOn(m_hDevice); + + // Set acquisition thread run flag + m_pobjAcqThread->m_bAcquisitionThreadFlag = true; + + // Acquisition thread start + m_pobjAcqThread->start(); + + // isStart flag set true + m_bAcquisitionStart = true; + + return; +} + +void IrisCameraController::StopAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Turn off stream + emStatus = GXStreamOff(m_hDevice); + + // isStart flag set false + m_bAcquisitionStart = false; + + return; +} + +bool IrisCameraController::SetAcquisitionBufferNum() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + uint64_t ui64BufferNum = 0; + int64_t i64PayloadSize = 0; + + // Get device current payload size + emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &i64PayloadSize); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Set buffer quantity of acquisition queue + if (i64PayloadSize == 0) + { + return false; + } + + // Calculate a reasonable number of Buffers for different payload size + // Small ROI and high frame rate will requires more acquisition Buffer + const size_t MAX_MEMORY_SIZE = 8 * 1024 * 1024; // The maximum number of memory bytes available for allocating frame Buffer + const size_t MIN_BUFFER_NUM = 5; // Minimum frame Buffer number + const size_t MAX_BUFFER_NUM = 450; // Maximum frame Buffer number + ui64BufferNum = MAX_MEMORY_SIZE / i64PayloadSize; + ui64BufferNum = (ui64BufferNum <= MIN_BUFFER_NUM) ? MIN_BUFFER_NUM : ui64BufferNum; + ui64BufferNum = (ui64BufferNum >= MAX_BUFFER_NUM) ? MAX_BUFFER_NUM : ui64BufferNum; + + emStatus = GXSetAcqusitionBufferNumber(m_hDevice, ui64BufferNum); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Transfer buffer number to acquisition thread class for using GXDQAllBufs + m_pobjAcqThread->m_ui64AcquisitionBufferNum = ui64BufferNum; + + return true; } diff --git a/device/IrisCameraController.h b/device/IrisCameraController.h index 5d7e269..67cbe2f 100644 --- a/device/IrisCameraController.h +++ b/device/IrisCameraController.h @@ -1,11 +1,12 @@ -#ifndef IRISCAMERACONTROLLER_H +#ifndef IRISCAMERACONTROLLER_H #define IRISCAMERACONTROLLER_H #include -#include "IrisCameraCapEventHandler.h" +#include "AcquisitionThread.h" +#include "utils/UtilInclude.h" -class IrisCameraCapEventHandler; +#define ENUMRATE_TIME_OUT 200 class IrisCameraController : public QObject { @@ -14,36 +15,31 @@ explicit IrisCameraController(QObject *parent = nullptr); ~IrisCameraController(); - // 初始化并打开人脸相机 - void initIrisCamera(); void openIrisCamera(); void closeIrisCamera(); void startCapture(); void stopCapture(); - void getLeftAndRightEyeFrame(); + CAcquisitionThread * m_pobjAcqThread; + GX_DEV_HANDLE m_hDevice; ///< Device Handle + uint32_t m_ui32DeviceNum; ///< Device number enumerated - IrisCameraCapEventHandler * irisCamHandler; + bool m_bOpen; ///< Flag : camera is opened or not + bool m_bAcquisitionStart; ///< Flag : camera is acquiring or not private: - GxIAPICPP::gxdeviceinfo_vector irisCamList; - - CGXDevicePointer irisCamPtr; ///< 设备句柄 - - CGXStreamPointer irisStreamPtr; ///< 左眼设备流 - - CGXFeatureControlPointer irisFeaturePtr; ///< 左眼属性控制器 - - CGXFeatureControlPointer irisStreamFeaturePtr; ///< 左眼流层控制器对象 - - void OpenDevice(); + // 初始化并打开人脸相机 + void initIrisCameraController(); + void SetUpAcquisitionThread(); + void UpdateDeviceList(); + bool SetAcquisitionBufferNum(); + void StartAcquisition(); + void StopAcquisition(); signals: - -public slots: - void getOneFaceFrm(); - + void irisCameraInitError(); + void irisCameraTermError(); }; #endif // IRISCAMERACONTROLLER_H diff --git a/device/device.pri b/device/device.pri index d1330a0..583721b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,13 +1,14 @@ HEADERS += $$PWD/IrisCameraController.h -HEADERS += $$PWD/IrisCameraCapEventHandler.h -#HEADERS += $$PWD/iris/IrisRegistProcess.h +#HEADERS += $$PWD/IrisCameraCapEventHandler.h +HEADERS += $$PWD/Common.h +HEADERS += $$PWD/AcquisitionThread.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h SOURCES += $$PWD/IrisCameraController.cpp -SOURCES += $$PWD/IrisCameraCapEventHandler.cpp -#SOURCES += $$PWD/iris/IrisRegistProcess.cpp +#SOURCES += $$PWD/IrisCameraCapEventHandler.cpp +SOURCES += $$PWD/AcquisitionThread.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 38f54fe..e4c8a02 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -11,7 +11,7 @@ // 连接算法服务 clientUtil = new SocketClientUtil(this); - clientUtil->connect("192.168.83.223", 50007); + clientUtil->connect(SettingConfig::getInstance().DEBUG_SEGMENT_IP, 50007); // 调用socket发送消息 connect(this, &IrisRecogProcess::sendDataToExract, clientUtil, &SocketClientUtil::sendData); @@ -43,18 +43,18 @@ continue; } - // 1. 图像栈中没有图像则直接返回 - if (ProMemory::getInstance().isIrisQueueEmpty() == true) + // 1. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 + if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) { - qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); + qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } - // 2. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 - if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) + // 2. 图像栈中没有图像则直接返回 + if (ProMemory::getInstance().isIrisQueueEmpty() == true) { - qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); + qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } @@ -73,7 +73,7 @@ int findEyeLast = timer.elapsed(); qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); -// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.matData = cv::imread("/home/casic/code/irisLogs/145333.552.bmp", 0); // irisInfo.hasEye = true; // 4.1 没有找到眼睛则返回 @@ -117,11 +117,10 @@ // 缩放到320 * 240 cv::resize(segMat, segMat, cv::Size(SettingConfig::getInstance().IRIS_WIDTH * 0.5, SettingConfig::getInstance().IRIS_HEIGHT * 0.5)); - - // std::string filename = QString("%1\\%2\\%3-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - // cv::imwrite(filename, segMat); - // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - +/* + std::string filename = QString("%1/%2/%3-seg.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(filename, segMat); +*/ int segMatSize = segMat.cols * segMat.rows; QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 @@ -167,9 +166,9 @@ // 成功接收后清除缓存区 clientUtil->resetRecvBuffer(); /* - std::string pupilSeg = QString("%1\\%2\\%3-pupil-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string maskSeg = QString("%1\\%2\\%3-mask-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string irisSeg = QString("%1\\%2\\%3-iris-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string pupilSeg = QString("%1/%2/%3-pupil-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); cv::imwrite(pupilSeg, pupil); cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); @@ -196,12 +195,20 @@ CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; irisInfo = casic::iris::CasicIrisInterface::getInstance().irisEncode(irisInfo); /* - std::string codeFilename = QString("%1\\%2\\%3-code.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string codeFilename = QString("%1/%2/%3-code.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string maskFilename = QString("%1/%2/%3-mask.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); */ + if (irisInfo.postProcSucc == false) { + qDebug() << "算法post process失败,暂停200ms"; + + addOneTryCount(); + this->msleep(THREAD_MSLEEP); // 200ms后再判断 + continue; + } + // 从编码中提取特征值 irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); @@ -211,6 +218,8 @@ CasicIrisRecState::getInstance().extractTmLast = encodeLast; CasicIrisRecState::getInstance().recogTimeLast += encodeLast; +// cv::imwrite(QString("%1/%2/%3.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(), irisInfo.matData); + // 开始匹配 timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) @@ -219,7 +228,7 @@ float score = casic::iris::CasicIrisInterface::getInstance().calculatePairPoints(feature.irisFeatureCode, irisInfo.irisFeatureCode); // 计算压缩编码的比较值 -// cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); +// cv::imwrite(QString("%1/%2/%3-%4.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; @@ -251,7 +260,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } @@ -268,7 +277,7 @@ CasicIrisRecState::getInstance().tryCount = 0; this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); emit failedMatchedIris(); @@ -290,7 +299,7 @@ // 识别失败时暂停工作 待返回识别界面时再开始工作和拍图 this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); } } else if (ProMemory::getInstance().appState == AppConstants::ApplicationState::STATE_WORKING) @@ -298,7 +307,8 @@ CasicIrisRecState::getInstance().noEyeCount++; // 如果在工作状态 则超过一定次数后返回待机 - if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT) + if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT && + SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT > 0) { // 发送信号待机 emit backToLockScreen(); diff --git a/device/iris/IrisRecogProcess.h b/device/iris/IrisRecogProcess.h index 9a3eec6..e21c1a7 100644 --- a/device/iris/IrisRecogProcess.h +++ b/device/iris/IrisRecogProcess.h @@ -1,4 +1,4 @@ -#ifndef IRISRECOGPROCESS_H +#ifndef IRISRECOGPROCESS_H #define IRISRECOGPROCESS_H #define THREAD_MSLEEP 200 @@ -10,6 +10,7 @@ #include "ProMemory.h" #include "device/iris/CasicIrisRecState.h" +#include "casic/iris/CasicIrisInterface.h" class IrisRecogProcess : public QThread { diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/device/IrisCameraCapEventHandler.h b/device/IrisCameraCapEventHandler.h index 8b976c5..94f5594 100644 --- a/device/IrisCameraCapEventHandler.h +++ b/device/IrisCameraCapEventHandler.h @@ -1,10 +1,9 @@ -#ifndef IRISCAMERACAPEVENTHANDLER_H +#ifndef IRISCAMERACAPEVENTHANDLER_H #define IRISCAMERACAPEVENTHANDLER_H #include #include -#include "include/opencv2/opencv.hpp" -#include "include/daheng/GalaxyIncludes.h" +#include #include "casic/iris/CasicIrisInterface.h" #include "ProMemory.h" diff --git a/device/IrisCameraController.cpp b/device/IrisCameraController.cpp index 0928176..4eea013 100644 --- a/device/IrisCameraController.cpp +++ b/device/IrisCameraController.cpp @@ -1,8 +1,8 @@ -#include "IrisCameraController.h" +#include "IrisCameraController.h" IrisCameraController::IrisCameraController(QObject *parent) : QObject(parent) { - this->irisCamHandler = new IrisCameraCapEventHandler(this); + initIrisCameraController(); } IrisCameraController::~IrisCameraController() { @@ -10,101 +10,204 @@ } -void IrisCameraController::initIrisCamera() +void IrisCameraController::initIrisCameraController() { - IGXFactory::GetInstance().Init(); + // Init GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXInitLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraInitError(); + LOG_ERROR("[CameraController]初始化虹膜相机失败"); + return ; + } + LOG_INFO("[CameraController]初始化虹膜相机成功"); //枚举设备 - IGXFactory::GetInstance().UpdateDeviceList(1000, irisCamList); - - this->OpenDevice(); + UpdateDeviceList(); } void IrisCameraController::openIrisCamera() { - //设置Buffer处理模式 - irisStreamFeaturePtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst"); + GX_STATUS emStatus = GX_STATUS_SUCCESS; - //注册回调函数 - irisStreamPtr->RegisterCaptureCallback(irisCamHandler, &irisCamPtr); + if (m_ui32DeviceNum > 0) { + emStatus = GXOpenDeviceByIndex(1, &m_hDevice); - //开启流层通道 - irisStreamPtr->StartGrab(); + if (emStatus == GX_STATUS_SUCCESS) { + LOG_INFO("[CameraController]开启虹膜相机成功"); - //发送开采命令 - irisFeaturePtr->GetCommandFeature("AcquisitionStart")->Execute(); + // isOpen flag set true + m_bOpen = true; - // 启动定时器 - TimeCounterUtil::getInstance().irisCapCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); // 50ms执行一次定时器 + SetUpAcquisitionThread(); + } + } + + return; } void IrisCameraController::closeIrisCamera() { - + // Release GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXCloseLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraTermError(); + } } void IrisCameraController::startCapture() { // 获取定时器, 绑定定时函数 - connect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString()); + bool bSetDone = false; + // Set acquisition buffer number + bSetDone = SetAcquisitionBufferNum(); + if (!bSetDone) + { + return; + } + + bool bPrepareDone = false; + // Alloc resource for image acquisition + bPrepareDone = m_pobjAcqThread->PrepareForShowImg(); + if (!bPrepareDone) + { + return; + } + + // Device start acquisition and start acquisition thread + StartAcquisition(); + + LOG_DEBUG(QString("[CameraController][startCapture]虹膜相机拍图").toStdString()); + + // Do not start timer when acquisition start failed + if (!m_bAcquisitionStart) + { + return; + } } void IrisCameraController::stopCapture() { - // 获取定时器, 绑定定时函数 - disconnect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString()); - + this->StopAcquisition(); } -void IrisCameraController::getOneFaceFrm() +void IrisCameraController::SetUpAcquisitionThread() { - // 发送软触发命令(在触发模式开启时有效) - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::getLeftAndRightEyeFrame() -{ - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::OpenDevice() -{ - auto device = irisCamList.at(0); - - irisCamPtr = IGXFactory::GetInstance().OpenDeviceByUserID(device.GetUserID(), GX_ACCESS_EXCLUSIVE); - irisFeaturePtr = irisCamPtr->GetRemoteFeatureControl(); - - // 判断设备流是否大于零, 如果大于零则打开流 - int nStreamCount = irisCamPtr->GetStreamCount(); - if (nStreamCount > 0) + // if Acquisition thread is on Stop acquisition thread + if (m_pobjAcqThread != NULL) { - irisStreamPtr = irisCamPtr->OpenStream(0); - irisStreamFeaturePtr = irisStreamPtr->GetFeatureControl(); + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Release acquisition thread object + RELEASE_ALLOC_MEM(m_pobjAcqThread); } - // 建议用户在打开网络相机之后, 根据当前网络环境设置相机的流通道包长值, - // 以提高网络相机的采集性能, 设置方法参考以下代码。 - GX_DEVICE_CLASS_LIST objDeviceClass = irisCamPtr->GetDeviceInfo().GetDeviceClass(); - if(GX_DEVICE_CLASS_GEV == objDeviceClass) + // Instantiation acquisition thread + try { - // 判断设备是否支持流通道数据包功能 - if(true == irisFeaturePtr->IsImplemented("GevSCPSPacketSize")) - { - // 获取当前网络环境的最优包长值 - int nPacketSize = irisStreamPtr->GetOptimalPacketSize(); - // 将最优包长值设置为当前设备的流通道包长值 - irisFeaturePtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize); - } + m_pobjAcqThread = new CAcquisitionThread(); + m_pobjAcqThread->m_hDevice = m_hDevice; + } + catch (std::bad_alloc &e) + { + QMessageBox::about(NULL, "Allocate memory error", "Cannot allocate memory, please exit this app!"); + RELEASE_ALLOC_MEM(m_pobjAcqThread); + return; } - //设置采集模式为连续采集模式 - irisFeaturePtr->GetEnumFeature("AcquisitionMode")->SetValue("Continuous"); + return; +} - //设置触发模式关 - irisFeaturePtr->GetEnumFeature("TriggerMode")->SetValue("On"); - irisFeaturePtr->GetEnumFeature("TriggerSource")->SetValue("Software"); +void IrisCameraController::UpdateDeviceList() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Enumerate Devcie List + emStatus = GXUpdateDeviceList(&m_ui32DeviceNum, ENUMRATE_TIME_OUT); + + LOG_INFO(QString("[CameraController]枚举虹膜相机成功[%1]").arg(m_ui32DeviceNum).toStdString()); + + return; +} + +void IrisCameraController::StartAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + emStatus = GXStreamOn(m_hDevice); + + // Set acquisition thread run flag + m_pobjAcqThread->m_bAcquisitionThreadFlag = true; + + // Acquisition thread start + m_pobjAcqThread->start(); + + // isStart flag set true + m_bAcquisitionStart = true; + + return; +} + +void IrisCameraController::StopAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Turn off stream + emStatus = GXStreamOff(m_hDevice); + + // isStart flag set false + m_bAcquisitionStart = false; + + return; +} + +bool IrisCameraController::SetAcquisitionBufferNum() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + uint64_t ui64BufferNum = 0; + int64_t i64PayloadSize = 0; + + // Get device current payload size + emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &i64PayloadSize); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Set buffer quantity of acquisition queue + if (i64PayloadSize == 0) + { + return false; + } + + // Calculate a reasonable number of Buffers for different payload size + // Small ROI and high frame rate will requires more acquisition Buffer + const size_t MAX_MEMORY_SIZE = 8 * 1024 * 1024; // The maximum number of memory bytes available for allocating frame Buffer + const size_t MIN_BUFFER_NUM = 5; // Minimum frame Buffer number + const size_t MAX_BUFFER_NUM = 450; // Maximum frame Buffer number + ui64BufferNum = MAX_MEMORY_SIZE / i64PayloadSize; + ui64BufferNum = (ui64BufferNum <= MIN_BUFFER_NUM) ? MIN_BUFFER_NUM : ui64BufferNum; + ui64BufferNum = (ui64BufferNum >= MAX_BUFFER_NUM) ? MAX_BUFFER_NUM : ui64BufferNum; + + emStatus = GXSetAcqusitionBufferNumber(m_hDevice, ui64BufferNum); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Transfer buffer number to acquisition thread class for using GXDQAllBufs + m_pobjAcqThread->m_ui64AcquisitionBufferNum = ui64BufferNum; + + return true; } diff --git a/device/IrisCameraController.h b/device/IrisCameraController.h index 5d7e269..67cbe2f 100644 --- a/device/IrisCameraController.h +++ b/device/IrisCameraController.h @@ -1,11 +1,12 @@ -#ifndef IRISCAMERACONTROLLER_H +#ifndef IRISCAMERACONTROLLER_H #define IRISCAMERACONTROLLER_H #include -#include "IrisCameraCapEventHandler.h" +#include "AcquisitionThread.h" +#include "utils/UtilInclude.h" -class IrisCameraCapEventHandler; +#define ENUMRATE_TIME_OUT 200 class IrisCameraController : public QObject { @@ -14,36 +15,31 @@ explicit IrisCameraController(QObject *parent = nullptr); ~IrisCameraController(); - // 初始化并打开人脸相机 - void initIrisCamera(); void openIrisCamera(); void closeIrisCamera(); void startCapture(); void stopCapture(); - void getLeftAndRightEyeFrame(); + CAcquisitionThread * m_pobjAcqThread; + GX_DEV_HANDLE m_hDevice; ///< Device Handle + uint32_t m_ui32DeviceNum; ///< Device number enumerated - IrisCameraCapEventHandler * irisCamHandler; + bool m_bOpen; ///< Flag : camera is opened or not + bool m_bAcquisitionStart; ///< Flag : camera is acquiring or not private: - GxIAPICPP::gxdeviceinfo_vector irisCamList; - - CGXDevicePointer irisCamPtr; ///< 设备句柄 - - CGXStreamPointer irisStreamPtr; ///< 左眼设备流 - - CGXFeatureControlPointer irisFeaturePtr; ///< 左眼属性控制器 - - CGXFeatureControlPointer irisStreamFeaturePtr; ///< 左眼流层控制器对象 - - void OpenDevice(); + // 初始化并打开人脸相机 + void initIrisCameraController(); + void SetUpAcquisitionThread(); + void UpdateDeviceList(); + bool SetAcquisitionBufferNum(); + void StartAcquisition(); + void StopAcquisition(); signals: - -public slots: - void getOneFaceFrm(); - + void irisCameraInitError(); + void irisCameraTermError(); }; #endif // IRISCAMERACONTROLLER_H diff --git a/device/device.pri b/device/device.pri index d1330a0..583721b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,13 +1,14 @@ HEADERS += $$PWD/IrisCameraController.h -HEADERS += $$PWD/IrisCameraCapEventHandler.h -#HEADERS += $$PWD/iris/IrisRegistProcess.h +#HEADERS += $$PWD/IrisCameraCapEventHandler.h +HEADERS += $$PWD/Common.h +HEADERS += $$PWD/AcquisitionThread.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h SOURCES += $$PWD/IrisCameraController.cpp -SOURCES += $$PWD/IrisCameraCapEventHandler.cpp -#SOURCES += $$PWD/iris/IrisRegistProcess.cpp +#SOURCES += $$PWD/IrisCameraCapEventHandler.cpp +SOURCES += $$PWD/AcquisitionThread.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 38f54fe..e4c8a02 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -11,7 +11,7 @@ // 连接算法服务 clientUtil = new SocketClientUtil(this); - clientUtil->connect("192.168.83.223", 50007); + clientUtil->connect(SettingConfig::getInstance().DEBUG_SEGMENT_IP, 50007); // 调用socket发送消息 connect(this, &IrisRecogProcess::sendDataToExract, clientUtil, &SocketClientUtil::sendData); @@ -43,18 +43,18 @@ continue; } - // 1. 图像栈中没有图像则直接返回 - if (ProMemory::getInstance().isIrisQueueEmpty() == true) + // 1. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 + if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) { - qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); + qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } - // 2. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 - if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) + // 2. 图像栈中没有图像则直接返回 + if (ProMemory::getInstance().isIrisQueueEmpty() == true) { - qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); + qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } @@ -73,7 +73,7 @@ int findEyeLast = timer.elapsed(); qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); -// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.matData = cv::imread("/home/casic/code/irisLogs/145333.552.bmp", 0); // irisInfo.hasEye = true; // 4.1 没有找到眼睛则返回 @@ -117,11 +117,10 @@ // 缩放到320 * 240 cv::resize(segMat, segMat, cv::Size(SettingConfig::getInstance().IRIS_WIDTH * 0.5, SettingConfig::getInstance().IRIS_HEIGHT * 0.5)); - - // std::string filename = QString("%1\\%2\\%3-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - // cv::imwrite(filename, segMat); - // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - +/* + std::string filename = QString("%1/%2/%3-seg.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(filename, segMat); +*/ int segMatSize = segMat.cols * segMat.rows; QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 @@ -167,9 +166,9 @@ // 成功接收后清除缓存区 clientUtil->resetRecvBuffer(); /* - std::string pupilSeg = QString("%1\\%2\\%3-pupil-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string maskSeg = QString("%1\\%2\\%3-mask-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string irisSeg = QString("%1\\%2\\%3-iris-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string pupilSeg = QString("%1/%2/%3-pupil-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); cv::imwrite(pupilSeg, pupil); cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); @@ -196,12 +195,20 @@ CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; irisInfo = casic::iris::CasicIrisInterface::getInstance().irisEncode(irisInfo); /* - std::string codeFilename = QString("%1\\%2\\%3-code.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string codeFilename = QString("%1/%2/%3-code.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string maskFilename = QString("%1/%2/%3-mask.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); */ + if (irisInfo.postProcSucc == false) { + qDebug() << "算法post process失败,暂停200ms"; + + addOneTryCount(); + this->msleep(THREAD_MSLEEP); // 200ms后再判断 + continue; + } + // 从编码中提取特征值 irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); @@ -211,6 +218,8 @@ CasicIrisRecState::getInstance().extractTmLast = encodeLast; CasicIrisRecState::getInstance().recogTimeLast += encodeLast; +// cv::imwrite(QString("%1/%2/%3.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(), irisInfo.matData); + // 开始匹配 timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) @@ -219,7 +228,7 @@ float score = casic::iris::CasicIrisInterface::getInstance().calculatePairPoints(feature.irisFeatureCode, irisInfo.irisFeatureCode); // 计算压缩编码的比较值 -// cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); +// cv::imwrite(QString("%1/%2/%3-%4.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; @@ -251,7 +260,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } @@ -268,7 +277,7 @@ CasicIrisRecState::getInstance().tryCount = 0; this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); emit failedMatchedIris(); @@ -290,7 +299,7 @@ // 识别失败时暂停工作 待返回识别界面时再开始工作和拍图 this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); } } else if (ProMemory::getInstance().appState == AppConstants::ApplicationState::STATE_WORKING) @@ -298,7 +307,8 @@ CasicIrisRecState::getInstance().noEyeCount++; // 如果在工作状态 则超过一定次数后返回待机 - if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT) + if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT && + SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT > 0) { // 发送信号待机 emit backToLockScreen(); diff --git a/device/iris/IrisRecogProcess.h b/device/iris/IrisRecogProcess.h index 9a3eec6..e21c1a7 100644 --- a/device/iris/IrisRecogProcess.h +++ b/device/iris/IrisRecogProcess.h @@ -1,4 +1,4 @@ -#ifndef IRISRECOGPROCESS_H +#ifndef IRISRECOGPROCESS_H #define IRISRECOGPROCESS_H #define THREAD_MSLEEP 200 @@ -10,6 +10,7 @@ #include "ProMemory.h" #include "device/iris/CasicIrisRecState.h" +#include "casic/iris/CasicIrisInterface.h" class IrisRecogProcess : public QThread { diff --git a/main.cpp b/main.cpp index 9052ddb..3bfb1c6 100644 --- a/main.cpp +++ b/main.cpp @@ -1,11 +1,11 @@ -#include "MainWindowForm.h" - -#include - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - MainWindowForm w; - w.show(); - return a.exec(); -} +#include "MainWindowForm.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindowForm w; + w.show(); + return a.exec(); +} diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/device/IrisCameraCapEventHandler.h b/device/IrisCameraCapEventHandler.h index 8b976c5..94f5594 100644 --- a/device/IrisCameraCapEventHandler.h +++ b/device/IrisCameraCapEventHandler.h @@ -1,10 +1,9 @@ -#ifndef IRISCAMERACAPEVENTHANDLER_H +#ifndef IRISCAMERACAPEVENTHANDLER_H #define IRISCAMERACAPEVENTHANDLER_H #include #include -#include "include/opencv2/opencv.hpp" -#include "include/daheng/GalaxyIncludes.h" +#include #include "casic/iris/CasicIrisInterface.h" #include "ProMemory.h" diff --git a/device/IrisCameraController.cpp b/device/IrisCameraController.cpp index 0928176..4eea013 100644 --- a/device/IrisCameraController.cpp +++ b/device/IrisCameraController.cpp @@ -1,8 +1,8 @@ -#include "IrisCameraController.h" +#include "IrisCameraController.h" IrisCameraController::IrisCameraController(QObject *parent) : QObject(parent) { - this->irisCamHandler = new IrisCameraCapEventHandler(this); + initIrisCameraController(); } IrisCameraController::~IrisCameraController() { @@ -10,101 +10,204 @@ } -void IrisCameraController::initIrisCamera() +void IrisCameraController::initIrisCameraController() { - IGXFactory::GetInstance().Init(); + // Init GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXInitLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraInitError(); + LOG_ERROR("[CameraController]初始化虹膜相机失败"); + return ; + } + LOG_INFO("[CameraController]初始化虹膜相机成功"); //枚举设备 - IGXFactory::GetInstance().UpdateDeviceList(1000, irisCamList); - - this->OpenDevice(); + UpdateDeviceList(); } void IrisCameraController::openIrisCamera() { - //设置Buffer处理模式 - irisStreamFeaturePtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst"); + GX_STATUS emStatus = GX_STATUS_SUCCESS; - //注册回调函数 - irisStreamPtr->RegisterCaptureCallback(irisCamHandler, &irisCamPtr); + if (m_ui32DeviceNum > 0) { + emStatus = GXOpenDeviceByIndex(1, &m_hDevice); - //开启流层通道 - irisStreamPtr->StartGrab(); + if (emStatus == GX_STATUS_SUCCESS) { + LOG_INFO("[CameraController]开启虹膜相机成功"); - //发送开采命令 - irisFeaturePtr->GetCommandFeature("AcquisitionStart")->Execute(); + // isOpen flag set true + m_bOpen = true; - // 启动定时器 - TimeCounterUtil::getInstance().irisCapCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); // 50ms执行一次定时器 + SetUpAcquisitionThread(); + } + } + + return; } void IrisCameraController::closeIrisCamera() { - + // Release GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXCloseLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraTermError(); + } } void IrisCameraController::startCapture() { // 获取定时器, 绑定定时函数 - connect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString()); + bool bSetDone = false; + // Set acquisition buffer number + bSetDone = SetAcquisitionBufferNum(); + if (!bSetDone) + { + return; + } + + bool bPrepareDone = false; + // Alloc resource for image acquisition + bPrepareDone = m_pobjAcqThread->PrepareForShowImg(); + if (!bPrepareDone) + { + return; + } + + // Device start acquisition and start acquisition thread + StartAcquisition(); + + LOG_DEBUG(QString("[CameraController][startCapture]虹膜相机拍图").toStdString()); + + // Do not start timer when acquisition start failed + if (!m_bAcquisitionStart) + { + return; + } } void IrisCameraController::stopCapture() { - // 获取定时器, 绑定定时函数 - disconnect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString()); - + this->StopAcquisition(); } -void IrisCameraController::getOneFaceFrm() +void IrisCameraController::SetUpAcquisitionThread() { - // 发送软触发命令(在触发模式开启时有效) - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::getLeftAndRightEyeFrame() -{ - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::OpenDevice() -{ - auto device = irisCamList.at(0); - - irisCamPtr = IGXFactory::GetInstance().OpenDeviceByUserID(device.GetUserID(), GX_ACCESS_EXCLUSIVE); - irisFeaturePtr = irisCamPtr->GetRemoteFeatureControl(); - - // 判断设备流是否大于零, 如果大于零则打开流 - int nStreamCount = irisCamPtr->GetStreamCount(); - if (nStreamCount > 0) + // if Acquisition thread is on Stop acquisition thread + if (m_pobjAcqThread != NULL) { - irisStreamPtr = irisCamPtr->OpenStream(0); - irisStreamFeaturePtr = irisStreamPtr->GetFeatureControl(); + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Release acquisition thread object + RELEASE_ALLOC_MEM(m_pobjAcqThread); } - // 建议用户在打开网络相机之后, 根据当前网络环境设置相机的流通道包长值, - // 以提高网络相机的采集性能, 设置方法参考以下代码。 - GX_DEVICE_CLASS_LIST objDeviceClass = irisCamPtr->GetDeviceInfo().GetDeviceClass(); - if(GX_DEVICE_CLASS_GEV == objDeviceClass) + // Instantiation acquisition thread + try { - // 判断设备是否支持流通道数据包功能 - if(true == irisFeaturePtr->IsImplemented("GevSCPSPacketSize")) - { - // 获取当前网络环境的最优包长值 - int nPacketSize = irisStreamPtr->GetOptimalPacketSize(); - // 将最优包长值设置为当前设备的流通道包长值 - irisFeaturePtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize); - } + m_pobjAcqThread = new CAcquisitionThread(); + m_pobjAcqThread->m_hDevice = m_hDevice; + } + catch (std::bad_alloc &e) + { + QMessageBox::about(NULL, "Allocate memory error", "Cannot allocate memory, please exit this app!"); + RELEASE_ALLOC_MEM(m_pobjAcqThread); + return; } - //设置采集模式为连续采集模式 - irisFeaturePtr->GetEnumFeature("AcquisitionMode")->SetValue("Continuous"); + return; +} - //设置触发模式关 - irisFeaturePtr->GetEnumFeature("TriggerMode")->SetValue("On"); - irisFeaturePtr->GetEnumFeature("TriggerSource")->SetValue("Software"); +void IrisCameraController::UpdateDeviceList() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Enumerate Devcie List + emStatus = GXUpdateDeviceList(&m_ui32DeviceNum, ENUMRATE_TIME_OUT); + + LOG_INFO(QString("[CameraController]枚举虹膜相机成功[%1]").arg(m_ui32DeviceNum).toStdString()); + + return; +} + +void IrisCameraController::StartAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + emStatus = GXStreamOn(m_hDevice); + + // Set acquisition thread run flag + m_pobjAcqThread->m_bAcquisitionThreadFlag = true; + + // Acquisition thread start + m_pobjAcqThread->start(); + + // isStart flag set true + m_bAcquisitionStart = true; + + return; +} + +void IrisCameraController::StopAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Turn off stream + emStatus = GXStreamOff(m_hDevice); + + // isStart flag set false + m_bAcquisitionStart = false; + + return; +} + +bool IrisCameraController::SetAcquisitionBufferNum() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + uint64_t ui64BufferNum = 0; + int64_t i64PayloadSize = 0; + + // Get device current payload size + emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &i64PayloadSize); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Set buffer quantity of acquisition queue + if (i64PayloadSize == 0) + { + return false; + } + + // Calculate a reasonable number of Buffers for different payload size + // Small ROI and high frame rate will requires more acquisition Buffer + const size_t MAX_MEMORY_SIZE = 8 * 1024 * 1024; // The maximum number of memory bytes available for allocating frame Buffer + const size_t MIN_BUFFER_NUM = 5; // Minimum frame Buffer number + const size_t MAX_BUFFER_NUM = 450; // Maximum frame Buffer number + ui64BufferNum = MAX_MEMORY_SIZE / i64PayloadSize; + ui64BufferNum = (ui64BufferNum <= MIN_BUFFER_NUM) ? MIN_BUFFER_NUM : ui64BufferNum; + ui64BufferNum = (ui64BufferNum >= MAX_BUFFER_NUM) ? MAX_BUFFER_NUM : ui64BufferNum; + + emStatus = GXSetAcqusitionBufferNumber(m_hDevice, ui64BufferNum); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Transfer buffer number to acquisition thread class for using GXDQAllBufs + m_pobjAcqThread->m_ui64AcquisitionBufferNum = ui64BufferNum; + + return true; } diff --git a/device/IrisCameraController.h b/device/IrisCameraController.h index 5d7e269..67cbe2f 100644 --- a/device/IrisCameraController.h +++ b/device/IrisCameraController.h @@ -1,11 +1,12 @@ -#ifndef IRISCAMERACONTROLLER_H +#ifndef IRISCAMERACONTROLLER_H #define IRISCAMERACONTROLLER_H #include -#include "IrisCameraCapEventHandler.h" +#include "AcquisitionThread.h" +#include "utils/UtilInclude.h" -class IrisCameraCapEventHandler; +#define ENUMRATE_TIME_OUT 200 class IrisCameraController : public QObject { @@ -14,36 +15,31 @@ explicit IrisCameraController(QObject *parent = nullptr); ~IrisCameraController(); - // 初始化并打开人脸相机 - void initIrisCamera(); void openIrisCamera(); void closeIrisCamera(); void startCapture(); void stopCapture(); - void getLeftAndRightEyeFrame(); + CAcquisitionThread * m_pobjAcqThread; + GX_DEV_HANDLE m_hDevice; ///< Device Handle + uint32_t m_ui32DeviceNum; ///< Device number enumerated - IrisCameraCapEventHandler * irisCamHandler; + bool m_bOpen; ///< Flag : camera is opened or not + bool m_bAcquisitionStart; ///< Flag : camera is acquiring or not private: - GxIAPICPP::gxdeviceinfo_vector irisCamList; - - CGXDevicePointer irisCamPtr; ///< 设备句柄 - - CGXStreamPointer irisStreamPtr; ///< 左眼设备流 - - CGXFeatureControlPointer irisFeaturePtr; ///< 左眼属性控制器 - - CGXFeatureControlPointer irisStreamFeaturePtr; ///< 左眼流层控制器对象 - - void OpenDevice(); + // 初始化并打开人脸相机 + void initIrisCameraController(); + void SetUpAcquisitionThread(); + void UpdateDeviceList(); + bool SetAcquisitionBufferNum(); + void StartAcquisition(); + void StopAcquisition(); signals: - -public slots: - void getOneFaceFrm(); - + void irisCameraInitError(); + void irisCameraTermError(); }; #endif // IRISCAMERACONTROLLER_H diff --git a/device/device.pri b/device/device.pri index d1330a0..583721b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,13 +1,14 @@ HEADERS += $$PWD/IrisCameraController.h -HEADERS += $$PWD/IrisCameraCapEventHandler.h -#HEADERS += $$PWD/iris/IrisRegistProcess.h +#HEADERS += $$PWD/IrisCameraCapEventHandler.h +HEADERS += $$PWD/Common.h +HEADERS += $$PWD/AcquisitionThread.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h SOURCES += $$PWD/IrisCameraController.cpp -SOURCES += $$PWD/IrisCameraCapEventHandler.cpp -#SOURCES += $$PWD/iris/IrisRegistProcess.cpp +#SOURCES += $$PWD/IrisCameraCapEventHandler.cpp +SOURCES += $$PWD/AcquisitionThread.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 38f54fe..e4c8a02 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -11,7 +11,7 @@ // 连接算法服务 clientUtil = new SocketClientUtil(this); - clientUtil->connect("192.168.83.223", 50007); + clientUtil->connect(SettingConfig::getInstance().DEBUG_SEGMENT_IP, 50007); // 调用socket发送消息 connect(this, &IrisRecogProcess::sendDataToExract, clientUtil, &SocketClientUtil::sendData); @@ -43,18 +43,18 @@ continue; } - // 1. 图像栈中没有图像则直接返回 - if (ProMemory::getInstance().isIrisQueueEmpty() == true) + // 1. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 + if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) { - qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); + qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } - // 2. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 - if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) + // 2. 图像栈中没有图像则直接返回 + if (ProMemory::getInstance().isIrisQueueEmpty() == true) { - qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); + qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } @@ -73,7 +73,7 @@ int findEyeLast = timer.elapsed(); qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); -// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.matData = cv::imread("/home/casic/code/irisLogs/145333.552.bmp", 0); // irisInfo.hasEye = true; // 4.1 没有找到眼睛则返回 @@ -117,11 +117,10 @@ // 缩放到320 * 240 cv::resize(segMat, segMat, cv::Size(SettingConfig::getInstance().IRIS_WIDTH * 0.5, SettingConfig::getInstance().IRIS_HEIGHT * 0.5)); - - // std::string filename = QString("%1\\%2\\%3-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - // cv::imwrite(filename, segMat); - // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - +/* + std::string filename = QString("%1/%2/%3-seg.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(filename, segMat); +*/ int segMatSize = segMat.cols * segMat.rows; QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 @@ -167,9 +166,9 @@ // 成功接收后清除缓存区 clientUtil->resetRecvBuffer(); /* - std::string pupilSeg = QString("%1\\%2\\%3-pupil-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string maskSeg = QString("%1\\%2\\%3-mask-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string irisSeg = QString("%1\\%2\\%3-iris-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string pupilSeg = QString("%1/%2/%3-pupil-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); cv::imwrite(pupilSeg, pupil); cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); @@ -196,12 +195,20 @@ CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; irisInfo = casic::iris::CasicIrisInterface::getInstance().irisEncode(irisInfo); /* - std::string codeFilename = QString("%1\\%2\\%3-code.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string codeFilename = QString("%1/%2/%3-code.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string maskFilename = QString("%1/%2/%3-mask.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); */ + if (irisInfo.postProcSucc == false) { + qDebug() << "算法post process失败,暂停200ms"; + + addOneTryCount(); + this->msleep(THREAD_MSLEEP); // 200ms后再判断 + continue; + } + // 从编码中提取特征值 irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); @@ -211,6 +218,8 @@ CasicIrisRecState::getInstance().extractTmLast = encodeLast; CasicIrisRecState::getInstance().recogTimeLast += encodeLast; +// cv::imwrite(QString("%1/%2/%3.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(), irisInfo.matData); + // 开始匹配 timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) @@ -219,7 +228,7 @@ float score = casic::iris::CasicIrisInterface::getInstance().calculatePairPoints(feature.irisFeatureCode, irisInfo.irisFeatureCode); // 计算压缩编码的比较值 -// cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); +// cv::imwrite(QString("%1/%2/%3-%4.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; @@ -251,7 +260,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } @@ -268,7 +277,7 @@ CasicIrisRecState::getInstance().tryCount = 0; this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); emit failedMatchedIris(); @@ -290,7 +299,7 @@ // 识别失败时暂停工作 待返回识别界面时再开始工作和拍图 this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); } } else if (ProMemory::getInstance().appState == AppConstants::ApplicationState::STATE_WORKING) @@ -298,7 +307,8 @@ CasicIrisRecState::getInstance().noEyeCount++; // 如果在工作状态 则超过一定次数后返回待机 - if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT) + if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT && + SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT > 0) { // 发送信号待机 emit backToLockScreen(); diff --git a/device/iris/IrisRecogProcess.h b/device/iris/IrisRecogProcess.h index 9a3eec6..e21c1a7 100644 --- a/device/iris/IrisRecogProcess.h +++ b/device/iris/IrisRecogProcess.h @@ -1,4 +1,4 @@ -#ifndef IRISRECOGPROCESS_H +#ifndef IRISRECOGPROCESS_H #define IRISRECOGPROCESS_H #define THREAD_MSLEEP 200 @@ -10,6 +10,7 @@ #include "ProMemory.h" #include "device/iris/CasicIrisRecState.h" +#include "casic/iris/CasicIrisInterface.h" class IrisRecogProcess : public QThread { diff --git a/main.cpp b/main.cpp index 9052ddb..3bfb1c6 100644 --- a/main.cpp +++ b/main.cpp @@ -1,11 +1,11 @@ -#include "MainWindowForm.h" - -#include - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - MainWindowForm w; - w.show(); - return a.exec(); -} +#include "MainWindowForm.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindowForm w; + w.show(); + return a.exec(); +} diff --git a/utils/ImageUtil.cpp b/utils/ImageUtil.cpp index ff77331..d40ea79 100644 --- a/utils/ImageUtil.cpp +++ b/utils/ImageUtil.cpp @@ -1,107 +1,107 @@ -#include "ImageUtil.h" - -ImageUtil::ImageUtil() -{ - -} - -QImage ImageUtil::MatImageToQImage(const cv::Mat &src) -{ - //CV_8UC1 8位无符号的单通道---灰度图片 - if(src.type() == CV_8UC1) - { - QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); - return qImage; - } - //为3通道的彩色图片 - else if(src.type() == CV_8UC3) - { - //得到图像的的首地址 - const uchar *pSrc = (const uchar*)src.data; - //以src构造图片 - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); - } - //四通道图片, 带Alpha通道的RGB彩色图像 - else if(src.type() == CV_8UC4) - { - const uchar *pSrc = (const uchar*)src.data; - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); - //返回图像的子区域作为一个新图像 - return qImage.copy(); - } - else - { - return QImage(); - } -} - -cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) -{ - cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); - return img; -} - -cv::Mat ImageUtil::QImageToMat(QImage image) -{ - cv::Mat mat; - switch(image.format()) - { - case QImage::Format_ARGB32: - case QImage::Format_RGB32: - case QImage::Format_ARGB32_Premultiplied: - mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_RGB888: - mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); - cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); - break; - case QImage::Format_Indexed8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_Grayscale8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); - break; - - default: - break; - } - - mat = mat.clone(); - - return mat; -} - -/* -QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) -{ - QImage qImage(data, width, height, format); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); -} - -QString ImageUtil::QImageToBase64(QImage image) -{ - QByteArray ba; - QBuffer buf(&ba); - image.save(&buf, "bmp"); - QString base64String = ba.toBase64(); - return base64String; -} - -cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) -{ - cv::Mat matClone = src.clone(); - cv::Rect bigRect; - - bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; - bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; - bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; - bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; - - cv::Mat roi = matClone(bigRect); - - return roi; -} -*/ +#include "ImageUtil.h" + +ImageUtil::ImageUtil() +{ + +} + +QImage ImageUtil::MatImageToQImage(const cv::Mat &src) +{ + //CV_8UC1 8位无符号的单通道---灰度图片 + if(src.type() == CV_8UC1) + { + QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); + return qImage; + } + //为3通道的彩色图片 + else if(src.type() == CV_8UC3) + { + //得到图像的的首地址 + const uchar *pSrc = (const uchar*)src.data; + //以src构造图片 + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); + } + //四通道图片, 带Alpha通道的RGB彩色图像 + else if(src.type() == CV_8UC4) + { + const uchar *pSrc = (const uchar*)src.data; + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); + //返回图像的子区域作为一个新图像 + return qImage.copy(); + } + else + { + return QImage(); + } +} + +cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) +{ + cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); + return img; +} + +cv::Mat ImageUtil::QImageToMat(QImage image) +{ + cv::Mat mat; + switch(image.format()) + { + case QImage::Format_ARGB32: + case QImage::Format_RGB32: + case QImage::Format_ARGB32_Premultiplied: + mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_RGB888: + mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); + cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); + break; + case QImage::Format_Indexed8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_Grayscale8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); + break; + + default: + break; + } + + mat = mat.clone(); + + return mat; +} + +/* +QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) +{ + QImage qImage(data, width, height, format); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); +} + +QString ImageUtil::QImageToBase64(QImage image) +{ + QByteArray ba; + QBuffer buf(&ba); + image.save(&buf, "bmp"); + QString base64String = ba.toBase64(); + return base64String; +} + +cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) +{ + cv::Mat matClone = src.clone(); + cv::Rect bigRect; + + bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; + bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; + bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; + bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; + + cv::Mat roi = matClone(bigRect); + + return roi; +} +*/ diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/device/IrisCameraCapEventHandler.h b/device/IrisCameraCapEventHandler.h index 8b976c5..94f5594 100644 --- a/device/IrisCameraCapEventHandler.h +++ b/device/IrisCameraCapEventHandler.h @@ -1,10 +1,9 @@ -#ifndef IRISCAMERACAPEVENTHANDLER_H +#ifndef IRISCAMERACAPEVENTHANDLER_H #define IRISCAMERACAPEVENTHANDLER_H #include #include -#include "include/opencv2/opencv.hpp" -#include "include/daheng/GalaxyIncludes.h" +#include #include "casic/iris/CasicIrisInterface.h" #include "ProMemory.h" diff --git a/device/IrisCameraController.cpp b/device/IrisCameraController.cpp index 0928176..4eea013 100644 --- a/device/IrisCameraController.cpp +++ b/device/IrisCameraController.cpp @@ -1,8 +1,8 @@ -#include "IrisCameraController.h" +#include "IrisCameraController.h" IrisCameraController::IrisCameraController(QObject *parent) : QObject(parent) { - this->irisCamHandler = new IrisCameraCapEventHandler(this); + initIrisCameraController(); } IrisCameraController::~IrisCameraController() { @@ -10,101 +10,204 @@ } -void IrisCameraController::initIrisCamera() +void IrisCameraController::initIrisCameraController() { - IGXFactory::GetInstance().Init(); + // Init GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXInitLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraInitError(); + LOG_ERROR("[CameraController]初始化虹膜相机失败"); + return ; + } + LOG_INFO("[CameraController]初始化虹膜相机成功"); //枚举设备 - IGXFactory::GetInstance().UpdateDeviceList(1000, irisCamList); - - this->OpenDevice(); + UpdateDeviceList(); } void IrisCameraController::openIrisCamera() { - //设置Buffer处理模式 - irisStreamFeaturePtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst"); + GX_STATUS emStatus = GX_STATUS_SUCCESS; - //注册回调函数 - irisStreamPtr->RegisterCaptureCallback(irisCamHandler, &irisCamPtr); + if (m_ui32DeviceNum > 0) { + emStatus = GXOpenDeviceByIndex(1, &m_hDevice); - //开启流层通道 - irisStreamPtr->StartGrab(); + if (emStatus == GX_STATUS_SUCCESS) { + LOG_INFO("[CameraController]开启虹膜相机成功"); - //发送开采命令 - irisFeaturePtr->GetCommandFeature("AcquisitionStart")->Execute(); + // isOpen flag set true + m_bOpen = true; - // 启动定时器 - TimeCounterUtil::getInstance().irisCapCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); // 50ms执行一次定时器 + SetUpAcquisitionThread(); + } + } + + return; } void IrisCameraController::closeIrisCamera() { - + // Release GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXCloseLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraTermError(); + } } void IrisCameraController::startCapture() { // 获取定时器, 绑定定时函数 - connect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString()); + bool bSetDone = false; + // Set acquisition buffer number + bSetDone = SetAcquisitionBufferNum(); + if (!bSetDone) + { + return; + } + + bool bPrepareDone = false; + // Alloc resource for image acquisition + bPrepareDone = m_pobjAcqThread->PrepareForShowImg(); + if (!bPrepareDone) + { + return; + } + + // Device start acquisition and start acquisition thread + StartAcquisition(); + + LOG_DEBUG(QString("[CameraController][startCapture]虹膜相机拍图").toStdString()); + + // Do not start timer when acquisition start failed + if (!m_bAcquisitionStart) + { + return; + } } void IrisCameraController::stopCapture() { - // 获取定时器, 绑定定时函数 - disconnect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString()); - + this->StopAcquisition(); } -void IrisCameraController::getOneFaceFrm() +void IrisCameraController::SetUpAcquisitionThread() { - // 发送软触发命令(在触发模式开启时有效) - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::getLeftAndRightEyeFrame() -{ - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::OpenDevice() -{ - auto device = irisCamList.at(0); - - irisCamPtr = IGXFactory::GetInstance().OpenDeviceByUserID(device.GetUserID(), GX_ACCESS_EXCLUSIVE); - irisFeaturePtr = irisCamPtr->GetRemoteFeatureControl(); - - // 判断设备流是否大于零, 如果大于零则打开流 - int nStreamCount = irisCamPtr->GetStreamCount(); - if (nStreamCount > 0) + // if Acquisition thread is on Stop acquisition thread + if (m_pobjAcqThread != NULL) { - irisStreamPtr = irisCamPtr->OpenStream(0); - irisStreamFeaturePtr = irisStreamPtr->GetFeatureControl(); + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Release acquisition thread object + RELEASE_ALLOC_MEM(m_pobjAcqThread); } - // 建议用户在打开网络相机之后, 根据当前网络环境设置相机的流通道包长值, - // 以提高网络相机的采集性能, 设置方法参考以下代码。 - GX_DEVICE_CLASS_LIST objDeviceClass = irisCamPtr->GetDeviceInfo().GetDeviceClass(); - if(GX_DEVICE_CLASS_GEV == objDeviceClass) + // Instantiation acquisition thread + try { - // 判断设备是否支持流通道数据包功能 - if(true == irisFeaturePtr->IsImplemented("GevSCPSPacketSize")) - { - // 获取当前网络环境的最优包长值 - int nPacketSize = irisStreamPtr->GetOptimalPacketSize(); - // 将最优包长值设置为当前设备的流通道包长值 - irisFeaturePtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize); - } + m_pobjAcqThread = new CAcquisitionThread(); + m_pobjAcqThread->m_hDevice = m_hDevice; + } + catch (std::bad_alloc &e) + { + QMessageBox::about(NULL, "Allocate memory error", "Cannot allocate memory, please exit this app!"); + RELEASE_ALLOC_MEM(m_pobjAcqThread); + return; } - //设置采集模式为连续采集模式 - irisFeaturePtr->GetEnumFeature("AcquisitionMode")->SetValue("Continuous"); + return; +} - //设置触发模式关 - irisFeaturePtr->GetEnumFeature("TriggerMode")->SetValue("On"); - irisFeaturePtr->GetEnumFeature("TriggerSource")->SetValue("Software"); +void IrisCameraController::UpdateDeviceList() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Enumerate Devcie List + emStatus = GXUpdateDeviceList(&m_ui32DeviceNum, ENUMRATE_TIME_OUT); + + LOG_INFO(QString("[CameraController]枚举虹膜相机成功[%1]").arg(m_ui32DeviceNum).toStdString()); + + return; +} + +void IrisCameraController::StartAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + emStatus = GXStreamOn(m_hDevice); + + // Set acquisition thread run flag + m_pobjAcqThread->m_bAcquisitionThreadFlag = true; + + // Acquisition thread start + m_pobjAcqThread->start(); + + // isStart flag set true + m_bAcquisitionStart = true; + + return; +} + +void IrisCameraController::StopAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Turn off stream + emStatus = GXStreamOff(m_hDevice); + + // isStart flag set false + m_bAcquisitionStart = false; + + return; +} + +bool IrisCameraController::SetAcquisitionBufferNum() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + uint64_t ui64BufferNum = 0; + int64_t i64PayloadSize = 0; + + // Get device current payload size + emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &i64PayloadSize); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Set buffer quantity of acquisition queue + if (i64PayloadSize == 0) + { + return false; + } + + // Calculate a reasonable number of Buffers for different payload size + // Small ROI and high frame rate will requires more acquisition Buffer + const size_t MAX_MEMORY_SIZE = 8 * 1024 * 1024; // The maximum number of memory bytes available for allocating frame Buffer + const size_t MIN_BUFFER_NUM = 5; // Minimum frame Buffer number + const size_t MAX_BUFFER_NUM = 450; // Maximum frame Buffer number + ui64BufferNum = MAX_MEMORY_SIZE / i64PayloadSize; + ui64BufferNum = (ui64BufferNum <= MIN_BUFFER_NUM) ? MIN_BUFFER_NUM : ui64BufferNum; + ui64BufferNum = (ui64BufferNum >= MAX_BUFFER_NUM) ? MAX_BUFFER_NUM : ui64BufferNum; + + emStatus = GXSetAcqusitionBufferNumber(m_hDevice, ui64BufferNum); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Transfer buffer number to acquisition thread class for using GXDQAllBufs + m_pobjAcqThread->m_ui64AcquisitionBufferNum = ui64BufferNum; + + return true; } diff --git a/device/IrisCameraController.h b/device/IrisCameraController.h index 5d7e269..67cbe2f 100644 --- a/device/IrisCameraController.h +++ b/device/IrisCameraController.h @@ -1,11 +1,12 @@ -#ifndef IRISCAMERACONTROLLER_H +#ifndef IRISCAMERACONTROLLER_H #define IRISCAMERACONTROLLER_H #include -#include "IrisCameraCapEventHandler.h" +#include "AcquisitionThread.h" +#include "utils/UtilInclude.h" -class IrisCameraCapEventHandler; +#define ENUMRATE_TIME_OUT 200 class IrisCameraController : public QObject { @@ -14,36 +15,31 @@ explicit IrisCameraController(QObject *parent = nullptr); ~IrisCameraController(); - // 初始化并打开人脸相机 - void initIrisCamera(); void openIrisCamera(); void closeIrisCamera(); void startCapture(); void stopCapture(); - void getLeftAndRightEyeFrame(); + CAcquisitionThread * m_pobjAcqThread; + GX_DEV_HANDLE m_hDevice; ///< Device Handle + uint32_t m_ui32DeviceNum; ///< Device number enumerated - IrisCameraCapEventHandler * irisCamHandler; + bool m_bOpen; ///< Flag : camera is opened or not + bool m_bAcquisitionStart; ///< Flag : camera is acquiring or not private: - GxIAPICPP::gxdeviceinfo_vector irisCamList; - - CGXDevicePointer irisCamPtr; ///< 设备句柄 - - CGXStreamPointer irisStreamPtr; ///< 左眼设备流 - - CGXFeatureControlPointer irisFeaturePtr; ///< 左眼属性控制器 - - CGXFeatureControlPointer irisStreamFeaturePtr; ///< 左眼流层控制器对象 - - void OpenDevice(); + // 初始化并打开人脸相机 + void initIrisCameraController(); + void SetUpAcquisitionThread(); + void UpdateDeviceList(); + bool SetAcquisitionBufferNum(); + void StartAcquisition(); + void StopAcquisition(); signals: - -public slots: - void getOneFaceFrm(); - + void irisCameraInitError(); + void irisCameraTermError(); }; #endif // IRISCAMERACONTROLLER_H diff --git a/device/device.pri b/device/device.pri index d1330a0..583721b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,13 +1,14 @@ HEADERS += $$PWD/IrisCameraController.h -HEADERS += $$PWD/IrisCameraCapEventHandler.h -#HEADERS += $$PWD/iris/IrisRegistProcess.h +#HEADERS += $$PWD/IrisCameraCapEventHandler.h +HEADERS += $$PWD/Common.h +HEADERS += $$PWD/AcquisitionThread.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h SOURCES += $$PWD/IrisCameraController.cpp -SOURCES += $$PWD/IrisCameraCapEventHandler.cpp -#SOURCES += $$PWD/iris/IrisRegistProcess.cpp +#SOURCES += $$PWD/IrisCameraCapEventHandler.cpp +SOURCES += $$PWD/AcquisitionThread.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 38f54fe..e4c8a02 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -11,7 +11,7 @@ // 连接算法服务 clientUtil = new SocketClientUtil(this); - clientUtil->connect("192.168.83.223", 50007); + clientUtil->connect(SettingConfig::getInstance().DEBUG_SEGMENT_IP, 50007); // 调用socket发送消息 connect(this, &IrisRecogProcess::sendDataToExract, clientUtil, &SocketClientUtil::sendData); @@ -43,18 +43,18 @@ continue; } - // 1. 图像栈中没有图像则直接返回 - if (ProMemory::getInstance().isIrisQueueEmpty() == true) + // 1. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 + if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) { - qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); + qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } - // 2. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 - if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) + // 2. 图像栈中没有图像则直接返回 + if (ProMemory::getInstance().isIrisQueueEmpty() == true) { - qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); + qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } @@ -73,7 +73,7 @@ int findEyeLast = timer.elapsed(); qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); -// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.matData = cv::imread("/home/casic/code/irisLogs/145333.552.bmp", 0); // irisInfo.hasEye = true; // 4.1 没有找到眼睛则返回 @@ -117,11 +117,10 @@ // 缩放到320 * 240 cv::resize(segMat, segMat, cv::Size(SettingConfig::getInstance().IRIS_WIDTH * 0.5, SettingConfig::getInstance().IRIS_HEIGHT * 0.5)); - - // std::string filename = QString("%1\\%2\\%3-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - // cv::imwrite(filename, segMat); - // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - +/* + std::string filename = QString("%1/%2/%3-seg.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(filename, segMat); +*/ int segMatSize = segMat.cols * segMat.rows; QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 @@ -167,9 +166,9 @@ // 成功接收后清除缓存区 clientUtil->resetRecvBuffer(); /* - std::string pupilSeg = QString("%1\\%2\\%3-pupil-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string maskSeg = QString("%1\\%2\\%3-mask-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string irisSeg = QString("%1\\%2\\%3-iris-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string pupilSeg = QString("%1/%2/%3-pupil-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); cv::imwrite(pupilSeg, pupil); cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); @@ -196,12 +195,20 @@ CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; irisInfo = casic::iris::CasicIrisInterface::getInstance().irisEncode(irisInfo); /* - std::string codeFilename = QString("%1\\%2\\%3-code.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string codeFilename = QString("%1/%2/%3-code.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string maskFilename = QString("%1/%2/%3-mask.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); */ + if (irisInfo.postProcSucc == false) { + qDebug() << "算法post process失败,暂停200ms"; + + addOneTryCount(); + this->msleep(THREAD_MSLEEP); // 200ms后再判断 + continue; + } + // 从编码中提取特征值 irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); @@ -211,6 +218,8 @@ CasicIrisRecState::getInstance().extractTmLast = encodeLast; CasicIrisRecState::getInstance().recogTimeLast += encodeLast; +// cv::imwrite(QString("%1/%2/%3.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(), irisInfo.matData); + // 开始匹配 timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) @@ -219,7 +228,7 @@ float score = casic::iris::CasicIrisInterface::getInstance().calculatePairPoints(feature.irisFeatureCode, irisInfo.irisFeatureCode); // 计算压缩编码的比较值 -// cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); +// cv::imwrite(QString("%1/%2/%3-%4.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; @@ -251,7 +260,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } @@ -268,7 +277,7 @@ CasicIrisRecState::getInstance().tryCount = 0; this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); emit failedMatchedIris(); @@ -290,7 +299,7 @@ // 识别失败时暂停工作 待返回识别界面时再开始工作和拍图 this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); } } else if (ProMemory::getInstance().appState == AppConstants::ApplicationState::STATE_WORKING) @@ -298,7 +307,8 @@ CasicIrisRecState::getInstance().noEyeCount++; // 如果在工作状态 则超过一定次数后返回待机 - if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT) + if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT && + SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT > 0) { // 发送信号待机 emit backToLockScreen(); diff --git a/device/iris/IrisRecogProcess.h b/device/iris/IrisRecogProcess.h index 9a3eec6..e21c1a7 100644 --- a/device/iris/IrisRecogProcess.h +++ b/device/iris/IrisRecogProcess.h @@ -1,4 +1,4 @@ -#ifndef IRISRECOGPROCESS_H +#ifndef IRISRECOGPROCESS_H #define IRISRECOGPROCESS_H #define THREAD_MSLEEP 200 @@ -10,6 +10,7 @@ #include "ProMemory.h" #include "device/iris/CasicIrisRecState.h" +#include "casic/iris/CasicIrisInterface.h" class IrisRecogProcess : public QThread { diff --git a/main.cpp b/main.cpp index 9052ddb..3bfb1c6 100644 --- a/main.cpp +++ b/main.cpp @@ -1,11 +1,11 @@ -#include "MainWindowForm.h" - -#include - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - MainWindowForm w; - w.show(); - return a.exec(); -} +#include "MainWindowForm.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindowForm w; + w.show(); + return a.exec(); +} diff --git a/utils/ImageUtil.cpp b/utils/ImageUtil.cpp index ff77331..d40ea79 100644 --- a/utils/ImageUtil.cpp +++ b/utils/ImageUtil.cpp @@ -1,107 +1,107 @@ -#include "ImageUtil.h" - -ImageUtil::ImageUtil() -{ - -} - -QImage ImageUtil::MatImageToQImage(const cv::Mat &src) -{ - //CV_8UC1 8位无符号的单通道---灰度图片 - if(src.type() == CV_8UC1) - { - QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); - return qImage; - } - //为3通道的彩色图片 - else if(src.type() == CV_8UC3) - { - //得到图像的的首地址 - const uchar *pSrc = (const uchar*)src.data; - //以src构造图片 - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); - } - //四通道图片, 带Alpha通道的RGB彩色图像 - else if(src.type() == CV_8UC4) - { - const uchar *pSrc = (const uchar*)src.data; - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); - //返回图像的子区域作为一个新图像 - return qImage.copy(); - } - else - { - return QImage(); - } -} - -cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) -{ - cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); - return img; -} - -cv::Mat ImageUtil::QImageToMat(QImage image) -{ - cv::Mat mat; - switch(image.format()) - { - case QImage::Format_ARGB32: - case QImage::Format_RGB32: - case QImage::Format_ARGB32_Premultiplied: - mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_RGB888: - mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); - cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); - break; - case QImage::Format_Indexed8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_Grayscale8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); - break; - - default: - break; - } - - mat = mat.clone(); - - return mat; -} - -/* -QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) -{ - QImage qImage(data, width, height, format); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); -} - -QString ImageUtil::QImageToBase64(QImage image) -{ - QByteArray ba; - QBuffer buf(&ba); - image.save(&buf, "bmp"); - QString base64String = ba.toBase64(); - return base64String; -} - -cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) -{ - cv::Mat matClone = src.clone(); - cv::Rect bigRect; - - bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; - bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; - bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; - bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; - - cv::Mat roi = matClone(bigRect); - - return roi; -} -*/ +#include "ImageUtil.h" + +ImageUtil::ImageUtil() +{ + +} + +QImage ImageUtil::MatImageToQImage(const cv::Mat &src) +{ + //CV_8UC1 8位无符号的单通道---灰度图片 + if(src.type() == CV_8UC1) + { + QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); + return qImage; + } + //为3通道的彩色图片 + else if(src.type() == CV_8UC3) + { + //得到图像的的首地址 + const uchar *pSrc = (const uchar*)src.data; + //以src构造图片 + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); + } + //四通道图片, 带Alpha通道的RGB彩色图像 + else if(src.type() == CV_8UC4) + { + const uchar *pSrc = (const uchar*)src.data; + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); + //返回图像的子区域作为一个新图像 + return qImage.copy(); + } + else + { + return QImage(); + } +} + +cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) +{ + cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); + return img; +} + +cv::Mat ImageUtil::QImageToMat(QImage image) +{ + cv::Mat mat; + switch(image.format()) + { + case QImage::Format_ARGB32: + case QImage::Format_RGB32: + case QImage::Format_ARGB32_Premultiplied: + mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_RGB888: + mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); + cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); + break; + case QImage::Format_Indexed8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_Grayscale8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); + break; + + default: + break; + } + + mat = mat.clone(); + + return mat; +} + +/* +QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) +{ + QImage qImage(data, width, height, format); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); +} + +QString ImageUtil::QImageToBase64(QImage image) +{ + QByteArray ba; + QBuffer buf(&ba); + image.save(&buf, "bmp"); + QString base64String = ba.toBase64(); + return base64String; +} + +cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) +{ + cv::Mat matClone = src.clone(); + cv::Rect bigRect; + + bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; + bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; + bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; + bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; + + cv::Mat roi = matClone(bigRect); + + return roi; +} +*/ diff --git a/utils/ImageUtil.h b/utils/ImageUtil.h index d9bf00a..4b702f4 100644 --- a/utils/ImageUtil.h +++ b/utils/ImageUtil.h @@ -1,23 +1,23 @@ -#ifndef IMAGEUTIL_H -#define IMAGEUTIL_H - -#include -#include -#include "opencv2/opencv.hpp" - -class ImageUtil -{ -public: - ImageUtil(); - - static QImage MatImageToQImage(const cv::Mat &src); -// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); - - static cv::Mat ucharToMat(unsigned char * data, int row, int col); - static cv::Mat QImageToMat(QImage image); -// static QString QImageToBase64(QImage image); - -// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); -}; - -#endif // IMAGEUTIL_H +#ifndef IMAGEUTIL_H +#define IMAGEUTIL_H + +#include +#include +#include "opencv2/opencv.hpp" + +class ImageUtil +{ +public: + ImageUtil(); + + static QImage MatImageToQImage(const cv::Mat &src); +// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); + + static cv::Mat ucharToMat(unsigned char * data, int row, int col); + static cv::Mat QImageToMat(QImage image); +// static QString QImageToBase64(QImage image); + +// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); +}; + +#endif // IMAGEUTIL_H diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/device/IrisCameraCapEventHandler.h b/device/IrisCameraCapEventHandler.h index 8b976c5..94f5594 100644 --- a/device/IrisCameraCapEventHandler.h +++ b/device/IrisCameraCapEventHandler.h @@ -1,10 +1,9 @@ -#ifndef IRISCAMERACAPEVENTHANDLER_H +#ifndef IRISCAMERACAPEVENTHANDLER_H #define IRISCAMERACAPEVENTHANDLER_H #include #include -#include "include/opencv2/opencv.hpp" -#include "include/daheng/GalaxyIncludes.h" +#include #include "casic/iris/CasicIrisInterface.h" #include "ProMemory.h" diff --git a/device/IrisCameraController.cpp b/device/IrisCameraController.cpp index 0928176..4eea013 100644 --- a/device/IrisCameraController.cpp +++ b/device/IrisCameraController.cpp @@ -1,8 +1,8 @@ -#include "IrisCameraController.h" +#include "IrisCameraController.h" IrisCameraController::IrisCameraController(QObject *parent) : QObject(parent) { - this->irisCamHandler = new IrisCameraCapEventHandler(this); + initIrisCameraController(); } IrisCameraController::~IrisCameraController() { @@ -10,101 +10,204 @@ } -void IrisCameraController::initIrisCamera() +void IrisCameraController::initIrisCameraController() { - IGXFactory::GetInstance().Init(); + // Init GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXInitLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraInitError(); + LOG_ERROR("[CameraController]初始化虹膜相机失败"); + return ; + } + LOG_INFO("[CameraController]初始化虹膜相机成功"); //枚举设备 - IGXFactory::GetInstance().UpdateDeviceList(1000, irisCamList); - - this->OpenDevice(); + UpdateDeviceList(); } void IrisCameraController::openIrisCamera() { - //设置Buffer处理模式 - irisStreamFeaturePtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst"); + GX_STATUS emStatus = GX_STATUS_SUCCESS; - //注册回调函数 - irisStreamPtr->RegisterCaptureCallback(irisCamHandler, &irisCamPtr); + if (m_ui32DeviceNum > 0) { + emStatus = GXOpenDeviceByIndex(1, &m_hDevice); - //开启流层通道 - irisStreamPtr->StartGrab(); + if (emStatus == GX_STATUS_SUCCESS) { + LOG_INFO("[CameraController]开启虹膜相机成功"); - //发送开采命令 - irisFeaturePtr->GetCommandFeature("AcquisitionStart")->Execute(); + // isOpen flag set true + m_bOpen = true; - // 启动定时器 - TimeCounterUtil::getInstance().irisCapCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); // 50ms执行一次定时器 + SetUpAcquisitionThread(); + } + } + + return; } void IrisCameraController::closeIrisCamera() { - + // Release GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXCloseLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraTermError(); + } } void IrisCameraController::startCapture() { // 获取定时器, 绑定定时函数 - connect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString()); + bool bSetDone = false; + // Set acquisition buffer number + bSetDone = SetAcquisitionBufferNum(); + if (!bSetDone) + { + return; + } + + bool bPrepareDone = false; + // Alloc resource for image acquisition + bPrepareDone = m_pobjAcqThread->PrepareForShowImg(); + if (!bPrepareDone) + { + return; + } + + // Device start acquisition and start acquisition thread + StartAcquisition(); + + LOG_DEBUG(QString("[CameraController][startCapture]虹膜相机拍图").toStdString()); + + // Do not start timer when acquisition start failed + if (!m_bAcquisitionStart) + { + return; + } } void IrisCameraController::stopCapture() { - // 获取定时器, 绑定定时函数 - disconnect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString()); - + this->StopAcquisition(); } -void IrisCameraController::getOneFaceFrm() +void IrisCameraController::SetUpAcquisitionThread() { - // 发送软触发命令(在触发模式开启时有效) - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::getLeftAndRightEyeFrame() -{ - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::OpenDevice() -{ - auto device = irisCamList.at(0); - - irisCamPtr = IGXFactory::GetInstance().OpenDeviceByUserID(device.GetUserID(), GX_ACCESS_EXCLUSIVE); - irisFeaturePtr = irisCamPtr->GetRemoteFeatureControl(); - - // 判断设备流是否大于零, 如果大于零则打开流 - int nStreamCount = irisCamPtr->GetStreamCount(); - if (nStreamCount > 0) + // if Acquisition thread is on Stop acquisition thread + if (m_pobjAcqThread != NULL) { - irisStreamPtr = irisCamPtr->OpenStream(0); - irisStreamFeaturePtr = irisStreamPtr->GetFeatureControl(); + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Release acquisition thread object + RELEASE_ALLOC_MEM(m_pobjAcqThread); } - // 建议用户在打开网络相机之后, 根据当前网络环境设置相机的流通道包长值, - // 以提高网络相机的采集性能, 设置方法参考以下代码。 - GX_DEVICE_CLASS_LIST objDeviceClass = irisCamPtr->GetDeviceInfo().GetDeviceClass(); - if(GX_DEVICE_CLASS_GEV == objDeviceClass) + // Instantiation acquisition thread + try { - // 判断设备是否支持流通道数据包功能 - if(true == irisFeaturePtr->IsImplemented("GevSCPSPacketSize")) - { - // 获取当前网络环境的最优包长值 - int nPacketSize = irisStreamPtr->GetOptimalPacketSize(); - // 将最优包长值设置为当前设备的流通道包长值 - irisFeaturePtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize); - } + m_pobjAcqThread = new CAcquisitionThread(); + m_pobjAcqThread->m_hDevice = m_hDevice; + } + catch (std::bad_alloc &e) + { + QMessageBox::about(NULL, "Allocate memory error", "Cannot allocate memory, please exit this app!"); + RELEASE_ALLOC_MEM(m_pobjAcqThread); + return; } - //设置采集模式为连续采集模式 - irisFeaturePtr->GetEnumFeature("AcquisitionMode")->SetValue("Continuous"); + return; +} - //设置触发模式关 - irisFeaturePtr->GetEnumFeature("TriggerMode")->SetValue("On"); - irisFeaturePtr->GetEnumFeature("TriggerSource")->SetValue("Software"); +void IrisCameraController::UpdateDeviceList() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Enumerate Devcie List + emStatus = GXUpdateDeviceList(&m_ui32DeviceNum, ENUMRATE_TIME_OUT); + + LOG_INFO(QString("[CameraController]枚举虹膜相机成功[%1]").arg(m_ui32DeviceNum).toStdString()); + + return; +} + +void IrisCameraController::StartAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + emStatus = GXStreamOn(m_hDevice); + + // Set acquisition thread run flag + m_pobjAcqThread->m_bAcquisitionThreadFlag = true; + + // Acquisition thread start + m_pobjAcqThread->start(); + + // isStart flag set true + m_bAcquisitionStart = true; + + return; +} + +void IrisCameraController::StopAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Turn off stream + emStatus = GXStreamOff(m_hDevice); + + // isStart flag set false + m_bAcquisitionStart = false; + + return; +} + +bool IrisCameraController::SetAcquisitionBufferNum() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + uint64_t ui64BufferNum = 0; + int64_t i64PayloadSize = 0; + + // Get device current payload size + emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &i64PayloadSize); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Set buffer quantity of acquisition queue + if (i64PayloadSize == 0) + { + return false; + } + + // Calculate a reasonable number of Buffers for different payload size + // Small ROI and high frame rate will requires more acquisition Buffer + const size_t MAX_MEMORY_SIZE = 8 * 1024 * 1024; // The maximum number of memory bytes available for allocating frame Buffer + const size_t MIN_BUFFER_NUM = 5; // Minimum frame Buffer number + const size_t MAX_BUFFER_NUM = 450; // Maximum frame Buffer number + ui64BufferNum = MAX_MEMORY_SIZE / i64PayloadSize; + ui64BufferNum = (ui64BufferNum <= MIN_BUFFER_NUM) ? MIN_BUFFER_NUM : ui64BufferNum; + ui64BufferNum = (ui64BufferNum >= MAX_BUFFER_NUM) ? MAX_BUFFER_NUM : ui64BufferNum; + + emStatus = GXSetAcqusitionBufferNumber(m_hDevice, ui64BufferNum); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Transfer buffer number to acquisition thread class for using GXDQAllBufs + m_pobjAcqThread->m_ui64AcquisitionBufferNum = ui64BufferNum; + + return true; } diff --git a/device/IrisCameraController.h b/device/IrisCameraController.h index 5d7e269..67cbe2f 100644 --- a/device/IrisCameraController.h +++ b/device/IrisCameraController.h @@ -1,11 +1,12 @@ -#ifndef IRISCAMERACONTROLLER_H +#ifndef IRISCAMERACONTROLLER_H #define IRISCAMERACONTROLLER_H #include -#include "IrisCameraCapEventHandler.h" +#include "AcquisitionThread.h" +#include "utils/UtilInclude.h" -class IrisCameraCapEventHandler; +#define ENUMRATE_TIME_OUT 200 class IrisCameraController : public QObject { @@ -14,36 +15,31 @@ explicit IrisCameraController(QObject *parent = nullptr); ~IrisCameraController(); - // 初始化并打开人脸相机 - void initIrisCamera(); void openIrisCamera(); void closeIrisCamera(); void startCapture(); void stopCapture(); - void getLeftAndRightEyeFrame(); + CAcquisitionThread * m_pobjAcqThread; + GX_DEV_HANDLE m_hDevice; ///< Device Handle + uint32_t m_ui32DeviceNum; ///< Device number enumerated - IrisCameraCapEventHandler * irisCamHandler; + bool m_bOpen; ///< Flag : camera is opened or not + bool m_bAcquisitionStart; ///< Flag : camera is acquiring or not private: - GxIAPICPP::gxdeviceinfo_vector irisCamList; - - CGXDevicePointer irisCamPtr; ///< 设备句柄 - - CGXStreamPointer irisStreamPtr; ///< 左眼设备流 - - CGXFeatureControlPointer irisFeaturePtr; ///< 左眼属性控制器 - - CGXFeatureControlPointer irisStreamFeaturePtr; ///< 左眼流层控制器对象 - - void OpenDevice(); + // 初始化并打开人脸相机 + void initIrisCameraController(); + void SetUpAcquisitionThread(); + void UpdateDeviceList(); + bool SetAcquisitionBufferNum(); + void StartAcquisition(); + void StopAcquisition(); signals: - -public slots: - void getOneFaceFrm(); - + void irisCameraInitError(); + void irisCameraTermError(); }; #endif // IRISCAMERACONTROLLER_H diff --git a/device/device.pri b/device/device.pri index d1330a0..583721b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,13 +1,14 @@ HEADERS += $$PWD/IrisCameraController.h -HEADERS += $$PWD/IrisCameraCapEventHandler.h -#HEADERS += $$PWD/iris/IrisRegistProcess.h +#HEADERS += $$PWD/IrisCameraCapEventHandler.h +HEADERS += $$PWD/Common.h +HEADERS += $$PWD/AcquisitionThread.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h SOURCES += $$PWD/IrisCameraController.cpp -SOURCES += $$PWD/IrisCameraCapEventHandler.cpp -#SOURCES += $$PWD/iris/IrisRegistProcess.cpp +#SOURCES += $$PWD/IrisCameraCapEventHandler.cpp +SOURCES += $$PWD/AcquisitionThread.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 38f54fe..e4c8a02 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -11,7 +11,7 @@ // 连接算法服务 clientUtil = new SocketClientUtil(this); - clientUtil->connect("192.168.83.223", 50007); + clientUtil->connect(SettingConfig::getInstance().DEBUG_SEGMENT_IP, 50007); // 调用socket发送消息 connect(this, &IrisRecogProcess::sendDataToExract, clientUtil, &SocketClientUtil::sendData); @@ -43,18 +43,18 @@ continue; } - // 1. 图像栈中没有图像则直接返回 - if (ProMemory::getInstance().isIrisQueueEmpty() == true) + // 1. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 + if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) { - qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); + qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } - // 2. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 - if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) + // 2. 图像栈中没有图像则直接返回 + if (ProMemory::getInstance().isIrisQueueEmpty() == true) { - qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); + qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } @@ -73,7 +73,7 @@ int findEyeLast = timer.elapsed(); qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); -// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.matData = cv::imread("/home/casic/code/irisLogs/145333.552.bmp", 0); // irisInfo.hasEye = true; // 4.1 没有找到眼睛则返回 @@ -117,11 +117,10 @@ // 缩放到320 * 240 cv::resize(segMat, segMat, cv::Size(SettingConfig::getInstance().IRIS_WIDTH * 0.5, SettingConfig::getInstance().IRIS_HEIGHT * 0.5)); - - // std::string filename = QString("%1\\%2\\%3-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - // cv::imwrite(filename, segMat); - // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - +/* + std::string filename = QString("%1/%2/%3-seg.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(filename, segMat); +*/ int segMatSize = segMat.cols * segMat.rows; QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 @@ -167,9 +166,9 @@ // 成功接收后清除缓存区 clientUtil->resetRecvBuffer(); /* - std::string pupilSeg = QString("%1\\%2\\%3-pupil-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string maskSeg = QString("%1\\%2\\%3-mask-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string irisSeg = QString("%1\\%2\\%3-iris-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string pupilSeg = QString("%1/%2/%3-pupil-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); cv::imwrite(pupilSeg, pupil); cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); @@ -196,12 +195,20 @@ CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; irisInfo = casic::iris::CasicIrisInterface::getInstance().irisEncode(irisInfo); /* - std::string codeFilename = QString("%1\\%2\\%3-code.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string codeFilename = QString("%1/%2/%3-code.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string maskFilename = QString("%1/%2/%3-mask.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); */ + if (irisInfo.postProcSucc == false) { + qDebug() << "算法post process失败,暂停200ms"; + + addOneTryCount(); + this->msleep(THREAD_MSLEEP); // 200ms后再判断 + continue; + } + // 从编码中提取特征值 irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); @@ -211,6 +218,8 @@ CasicIrisRecState::getInstance().extractTmLast = encodeLast; CasicIrisRecState::getInstance().recogTimeLast += encodeLast; +// cv::imwrite(QString("%1/%2/%3.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(), irisInfo.matData); + // 开始匹配 timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) @@ -219,7 +228,7 @@ float score = casic::iris::CasicIrisInterface::getInstance().calculatePairPoints(feature.irisFeatureCode, irisInfo.irisFeatureCode); // 计算压缩编码的比较值 -// cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); +// cv::imwrite(QString("%1/%2/%3-%4.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; @@ -251,7 +260,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } @@ -268,7 +277,7 @@ CasicIrisRecState::getInstance().tryCount = 0; this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); emit failedMatchedIris(); @@ -290,7 +299,7 @@ // 识别失败时暂停工作 待返回识别界面时再开始工作和拍图 this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); } } else if (ProMemory::getInstance().appState == AppConstants::ApplicationState::STATE_WORKING) @@ -298,7 +307,8 @@ CasicIrisRecState::getInstance().noEyeCount++; // 如果在工作状态 则超过一定次数后返回待机 - if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT) + if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT && + SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT > 0) { // 发送信号待机 emit backToLockScreen(); diff --git a/device/iris/IrisRecogProcess.h b/device/iris/IrisRecogProcess.h index 9a3eec6..e21c1a7 100644 --- a/device/iris/IrisRecogProcess.h +++ b/device/iris/IrisRecogProcess.h @@ -1,4 +1,4 @@ -#ifndef IRISRECOGPROCESS_H +#ifndef IRISRECOGPROCESS_H #define IRISRECOGPROCESS_H #define THREAD_MSLEEP 200 @@ -10,6 +10,7 @@ #include "ProMemory.h" #include "device/iris/CasicIrisRecState.h" +#include "casic/iris/CasicIrisInterface.h" class IrisRecogProcess : public QThread { diff --git a/main.cpp b/main.cpp index 9052ddb..3bfb1c6 100644 --- a/main.cpp +++ b/main.cpp @@ -1,11 +1,11 @@ -#include "MainWindowForm.h" - -#include - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - MainWindowForm w; - w.show(); - return a.exec(); -} +#include "MainWindowForm.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindowForm w; + w.show(); + return a.exec(); +} diff --git a/utils/ImageUtil.cpp b/utils/ImageUtil.cpp index ff77331..d40ea79 100644 --- a/utils/ImageUtil.cpp +++ b/utils/ImageUtil.cpp @@ -1,107 +1,107 @@ -#include "ImageUtil.h" - -ImageUtil::ImageUtil() -{ - -} - -QImage ImageUtil::MatImageToQImage(const cv::Mat &src) -{ - //CV_8UC1 8位无符号的单通道---灰度图片 - if(src.type() == CV_8UC1) - { - QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); - return qImage; - } - //为3通道的彩色图片 - else if(src.type() == CV_8UC3) - { - //得到图像的的首地址 - const uchar *pSrc = (const uchar*)src.data; - //以src构造图片 - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); - } - //四通道图片, 带Alpha通道的RGB彩色图像 - else if(src.type() == CV_8UC4) - { - const uchar *pSrc = (const uchar*)src.data; - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); - //返回图像的子区域作为一个新图像 - return qImage.copy(); - } - else - { - return QImage(); - } -} - -cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) -{ - cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); - return img; -} - -cv::Mat ImageUtil::QImageToMat(QImage image) -{ - cv::Mat mat; - switch(image.format()) - { - case QImage::Format_ARGB32: - case QImage::Format_RGB32: - case QImage::Format_ARGB32_Premultiplied: - mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_RGB888: - mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); - cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); - break; - case QImage::Format_Indexed8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_Grayscale8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); - break; - - default: - break; - } - - mat = mat.clone(); - - return mat; -} - -/* -QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) -{ - QImage qImage(data, width, height, format); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); -} - -QString ImageUtil::QImageToBase64(QImage image) -{ - QByteArray ba; - QBuffer buf(&ba); - image.save(&buf, "bmp"); - QString base64String = ba.toBase64(); - return base64String; -} - -cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) -{ - cv::Mat matClone = src.clone(); - cv::Rect bigRect; - - bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; - bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; - bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; - bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; - - cv::Mat roi = matClone(bigRect); - - return roi; -} -*/ +#include "ImageUtil.h" + +ImageUtil::ImageUtil() +{ + +} + +QImage ImageUtil::MatImageToQImage(const cv::Mat &src) +{ + //CV_8UC1 8位无符号的单通道---灰度图片 + if(src.type() == CV_8UC1) + { + QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); + return qImage; + } + //为3通道的彩色图片 + else if(src.type() == CV_8UC3) + { + //得到图像的的首地址 + const uchar *pSrc = (const uchar*)src.data; + //以src构造图片 + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); + } + //四通道图片, 带Alpha通道的RGB彩色图像 + else if(src.type() == CV_8UC4) + { + const uchar *pSrc = (const uchar*)src.data; + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); + //返回图像的子区域作为一个新图像 + return qImage.copy(); + } + else + { + return QImage(); + } +} + +cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) +{ + cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); + return img; +} + +cv::Mat ImageUtil::QImageToMat(QImage image) +{ + cv::Mat mat; + switch(image.format()) + { + case QImage::Format_ARGB32: + case QImage::Format_RGB32: + case QImage::Format_ARGB32_Premultiplied: + mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_RGB888: + mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); + cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); + break; + case QImage::Format_Indexed8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_Grayscale8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); + break; + + default: + break; + } + + mat = mat.clone(); + + return mat; +} + +/* +QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) +{ + QImage qImage(data, width, height, format); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); +} + +QString ImageUtil::QImageToBase64(QImage image) +{ + QByteArray ba; + QBuffer buf(&ba); + image.save(&buf, "bmp"); + QString base64String = ba.toBase64(); + return base64String; +} + +cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) +{ + cv::Mat matClone = src.clone(); + cv::Rect bigRect; + + bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; + bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; + bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; + bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; + + cv::Mat roi = matClone(bigRect); + + return roi; +} +*/ diff --git a/utils/ImageUtil.h b/utils/ImageUtil.h index d9bf00a..4b702f4 100644 --- a/utils/ImageUtil.h +++ b/utils/ImageUtil.h @@ -1,23 +1,23 @@ -#ifndef IMAGEUTIL_H -#define IMAGEUTIL_H - -#include -#include -#include "opencv2/opencv.hpp" - -class ImageUtil -{ -public: - ImageUtil(); - - static QImage MatImageToQImage(const cv::Mat &src); -// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); - - static cv::Mat ucharToMat(unsigned char * data, int row, int col); - static cv::Mat QImageToMat(QImage image); -// static QString QImageToBase64(QImage image); - -// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); -}; - -#endif // IMAGEUTIL_H +#ifndef IMAGEUTIL_H +#define IMAGEUTIL_H + +#include +#include +#include "opencv2/opencv.hpp" + +class ImageUtil +{ +public: + ImageUtil(); + + static QImage MatImageToQImage(const cv::Mat &src); +// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); + + static cv::Mat ucharToMat(unsigned char * data, int row, int col); + static cv::Mat QImageToMat(QImage image); +// static QString QImageToBase64(QImage image); + +// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); +}; + +#endif // IMAGEUTIL_H diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp index 663db0f..05c4c68 100644 --- a/utils/SettingConfig.cpp +++ b/utils/SettingConfig.cpp @@ -1,4 +1,4 @@ -#include "SettingConfig.h" +#include "SettingConfig.h" #include SettingConfig::SettingConfig() @@ -34,6 +34,9 @@ LOG_FILE = getProperty("log", "logFile").toString(); LOG_LEVEL = getProperty("log", "logLevel").toString(); + + DEBUG_CAMERA_ROTATE = getProperty("debug", "cameraRotate").toString(); + DEBUG_SEGMENT_IP = getProperty("debug", "segmentIp").toString(); } diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/device/IrisCameraCapEventHandler.h b/device/IrisCameraCapEventHandler.h index 8b976c5..94f5594 100644 --- a/device/IrisCameraCapEventHandler.h +++ b/device/IrisCameraCapEventHandler.h @@ -1,10 +1,9 @@ -#ifndef IRISCAMERACAPEVENTHANDLER_H +#ifndef IRISCAMERACAPEVENTHANDLER_H #define IRISCAMERACAPEVENTHANDLER_H #include #include -#include "include/opencv2/opencv.hpp" -#include "include/daheng/GalaxyIncludes.h" +#include #include "casic/iris/CasicIrisInterface.h" #include "ProMemory.h" diff --git a/device/IrisCameraController.cpp b/device/IrisCameraController.cpp index 0928176..4eea013 100644 --- a/device/IrisCameraController.cpp +++ b/device/IrisCameraController.cpp @@ -1,8 +1,8 @@ -#include "IrisCameraController.h" +#include "IrisCameraController.h" IrisCameraController::IrisCameraController(QObject *parent) : QObject(parent) { - this->irisCamHandler = new IrisCameraCapEventHandler(this); + initIrisCameraController(); } IrisCameraController::~IrisCameraController() { @@ -10,101 +10,204 @@ } -void IrisCameraController::initIrisCamera() +void IrisCameraController::initIrisCameraController() { - IGXFactory::GetInstance().Init(); + // Init GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXInitLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraInitError(); + LOG_ERROR("[CameraController]初始化虹膜相机失败"); + return ; + } + LOG_INFO("[CameraController]初始化虹膜相机成功"); //枚举设备 - IGXFactory::GetInstance().UpdateDeviceList(1000, irisCamList); - - this->OpenDevice(); + UpdateDeviceList(); } void IrisCameraController::openIrisCamera() { - //设置Buffer处理模式 - irisStreamFeaturePtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst"); + GX_STATUS emStatus = GX_STATUS_SUCCESS; - //注册回调函数 - irisStreamPtr->RegisterCaptureCallback(irisCamHandler, &irisCamPtr); + if (m_ui32DeviceNum > 0) { + emStatus = GXOpenDeviceByIndex(1, &m_hDevice); - //开启流层通道 - irisStreamPtr->StartGrab(); + if (emStatus == GX_STATUS_SUCCESS) { + LOG_INFO("[CameraController]开启虹膜相机成功"); - //发送开采命令 - irisFeaturePtr->GetCommandFeature("AcquisitionStart")->Execute(); + // isOpen flag set true + m_bOpen = true; - // 启动定时器 - TimeCounterUtil::getInstance().irisCapCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); // 50ms执行一次定时器 + SetUpAcquisitionThread(); + } + } + + return; } void IrisCameraController::closeIrisCamera() { - + // Release GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXCloseLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraTermError(); + } } void IrisCameraController::startCapture() { // 获取定时器, 绑定定时函数 - connect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString()); + bool bSetDone = false; + // Set acquisition buffer number + bSetDone = SetAcquisitionBufferNum(); + if (!bSetDone) + { + return; + } + + bool bPrepareDone = false; + // Alloc resource for image acquisition + bPrepareDone = m_pobjAcqThread->PrepareForShowImg(); + if (!bPrepareDone) + { + return; + } + + // Device start acquisition and start acquisition thread + StartAcquisition(); + + LOG_DEBUG(QString("[CameraController][startCapture]虹膜相机拍图").toStdString()); + + // Do not start timer when acquisition start failed + if (!m_bAcquisitionStart) + { + return; + } } void IrisCameraController::stopCapture() { - // 获取定时器, 绑定定时函数 - disconnect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString()); - + this->StopAcquisition(); } -void IrisCameraController::getOneFaceFrm() +void IrisCameraController::SetUpAcquisitionThread() { - // 发送软触发命令(在触发模式开启时有效) - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::getLeftAndRightEyeFrame() -{ - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::OpenDevice() -{ - auto device = irisCamList.at(0); - - irisCamPtr = IGXFactory::GetInstance().OpenDeviceByUserID(device.GetUserID(), GX_ACCESS_EXCLUSIVE); - irisFeaturePtr = irisCamPtr->GetRemoteFeatureControl(); - - // 判断设备流是否大于零, 如果大于零则打开流 - int nStreamCount = irisCamPtr->GetStreamCount(); - if (nStreamCount > 0) + // if Acquisition thread is on Stop acquisition thread + if (m_pobjAcqThread != NULL) { - irisStreamPtr = irisCamPtr->OpenStream(0); - irisStreamFeaturePtr = irisStreamPtr->GetFeatureControl(); + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Release acquisition thread object + RELEASE_ALLOC_MEM(m_pobjAcqThread); } - // 建议用户在打开网络相机之后, 根据当前网络环境设置相机的流通道包长值, - // 以提高网络相机的采集性能, 设置方法参考以下代码。 - GX_DEVICE_CLASS_LIST objDeviceClass = irisCamPtr->GetDeviceInfo().GetDeviceClass(); - if(GX_DEVICE_CLASS_GEV == objDeviceClass) + // Instantiation acquisition thread + try { - // 判断设备是否支持流通道数据包功能 - if(true == irisFeaturePtr->IsImplemented("GevSCPSPacketSize")) - { - // 获取当前网络环境的最优包长值 - int nPacketSize = irisStreamPtr->GetOptimalPacketSize(); - // 将最优包长值设置为当前设备的流通道包长值 - irisFeaturePtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize); - } + m_pobjAcqThread = new CAcquisitionThread(); + m_pobjAcqThread->m_hDevice = m_hDevice; + } + catch (std::bad_alloc &e) + { + QMessageBox::about(NULL, "Allocate memory error", "Cannot allocate memory, please exit this app!"); + RELEASE_ALLOC_MEM(m_pobjAcqThread); + return; } - //设置采集模式为连续采集模式 - irisFeaturePtr->GetEnumFeature("AcquisitionMode")->SetValue("Continuous"); + return; +} - //设置触发模式关 - irisFeaturePtr->GetEnumFeature("TriggerMode")->SetValue("On"); - irisFeaturePtr->GetEnumFeature("TriggerSource")->SetValue("Software"); +void IrisCameraController::UpdateDeviceList() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Enumerate Devcie List + emStatus = GXUpdateDeviceList(&m_ui32DeviceNum, ENUMRATE_TIME_OUT); + + LOG_INFO(QString("[CameraController]枚举虹膜相机成功[%1]").arg(m_ui32DeviceNum).toStdString()); + + return; +} + +void IrisCameraController::StartAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + emStatus = GXStreamOn(m_hDevice); + + // Set acquisition thread run flag + m_pobjAcqThread->m_bAcquisitionThreadFlag = true; + + // Acquisition thread start + m_pobjAcqThread->start(); + + // isStart flag set true + m_bAcquisitionStart = true; + + return; +} + +void IrisCameraController::StopAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Turn off stream + emStatus = GXStreamOff(m_hDevice); + + // isStart flag set false + m_bAcquisitionStart = false; + + return; +} + +bool IrisCameraController::SetAcquisitionBufferNum() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + uint64_t ui64BufferNum = 0; + int64_t i64PayloadSize = 0; + + // Get device current payload size + emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &i64PayloadSize); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Set buffer quantity of acquisition queue + if (i64PayloadSize == 0) + { + return false; + } + + // Calculate a reasonable number of Buffers for different payload size + // Small ROI and high frame rate will requires more acquisition Buffer + const size_t MAX_MEMORY_SIZE = 8 * 1024 * 1024; // The maximum number of memory bytes available for allocating frame Buffer + const size_t MIN_BUFFER_NUM = 5; // Minimum frame Buffer number + const size_t MAX_BUFFER_NUM = 450; // Maximum frame Buffer number + ui64BufferNum = MAX_MEMORY_SIZE / i64PayloadSize; + ui64BufferNum = (ui64BufferNum <= MIN_BUFFER_NUM) ? MIN_BUFFER_NUM : ui64BufferNum; + ui64BufferNum = (ui64BufferNum >= MAX_BUFFER_NUM) ? MAX_BUFFER_NUM : ui64BufferNum; + + emStatus = GXSetAcqusitionBufferNumber(m_hDevice, ui64BufferNum); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Transfer buffer number to acquisition thread class for using GXDQAllBufs + m_pobjAcqThread->m_ui64AcquisitionBufferNum = ui64BufferNum; + + return true; } diff --git a/device/IrisCameraController.h b/device/IrisCameraController.h index 5d7e269..67cbe2f 100644 --- a/device/IrisCameraController.h +++ b/device/IrisCameraController.h @@ -1,11 +1,12 @@ -#ifndef IRISCAMERACONTROLLER_H +#ifndef IRISCAMERACONTROLLER_H #define IRISCAMERACONTROLLER_H #include -#include "IrisCameraCapEventHandler.h" +#include "AcquisitionThread.h" +#include "utils/UtilInclude.h" -class IrisCameraCapEventHandler; +#define ENUMRATE_TIME_OUT 200 class IrisCameraController : public QObject { @@ -14,36 +15,31 @@ explicit IrisCameraController(QObject *parent = nullptr); ~IrisCameraController(); - // 初始化并打开人脸相机 - void initIrisCamera(); void openIrisCamera(); void closeIrisCamera(); void startCapture(); void stopCapture(); - void getLeftAndRightEyeFrame(); + CAcquisitionThread * m_pobjAcqThread; + GX_DEV_HANDLE m_hDevice; ///< Device Handle + uint32_t m_ui32DeviceNum; ///< Device number enumerated - IrisCameraCapEventHandler * irisCamHandler; + bool m_bOpen; ///< Flag : camera is opened or not + bool m_bAcquisitionStart; ///< Flag : camera is acquiring or not private: - GxIAPICPP::gxdeviceinfo_vector irisCamList; - - CGXDevicePointer irisCamPtr; ///< 设备句柄 - - CGXStreamPointer irisStreamPtr; ///< 左眼设备流 - - CGXFeatureControlPointer irisFeaturePtr; ///< 左眼属性控制器 - - CGXFeatureControlPointer irisStreamFeaturePtr; ///< 左眼流层控制器对象 - - void OpenDevice(); + // 初始化并打开人脸相机 + void initIrisCameraController(); + void SetUpAcquisitionThread(); + void UpdateDeviceList(); + bool SetAcquisitionBufferNum(); + void StartAcquisition(); + void StopAcquisition(); signals: - -public slots: - void getOneFaceFrm(); - + void irisCameraInitError(); + void irisCameraTermError(); }; #endif // IRISCAMERACONTROLLER_H diff --git a/device/device.pri b/device/device.pri index d1330a0..583721b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,13 +1,14 @@ HEADERS += $$PWD/IrisCameraController.h -HEADERS += $$PWD/IrisCameraCapEventHandler.h -#HEADERS += $$PWD/iris/IrisRegistProcess.h +#HEADERS += $$PWD/IrisCameraCapEventHandler.h +HEADERS += $$PWD/Common.h +HEADERS += $$PWD/AcquisitionThread.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h SOURCES += $$PWD/IrisCameraController.cpp -SOURCES += $$PWD/IrisCameraCapEventHandler.cpp -#SOURCES += $$PWD/iris/IrisRegistProcess.cpp +#SOURCES += $$PWD/IrisCameraCapEventHandler.cpp +SOURCES += $$PWD/AcquisitionThread.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 38f54fe..e4c8a02 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -11,7 +11,7 @@ // 连接算法服务 clientUtil = new SocketClientUtil(this); - clientUtil->connect("192.168.83.223", 50007); + clientUtil->connect(SettingConfig::getInstance().DEBUG_SEGMENT_IP, 50007); // 调用socket发送消息 connect(this, &IrisRecogProcess::sendDataToExract, clientUtil, &SocketClientUtil::sendData); @@ -43,18 +43,18 @@ continue; } - // 1. 图像栈中没有图像则直接返回 - if (ProMemory::getInstance().isIrisQueueEmpty() == true) + // 1. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 + if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) { - qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); + qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } - // 2. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 - if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) + // 2. 图像栈中没有图像则直接返回 + if (ProMemory::getInstance().isIrisQueueEmpty() == true) { - qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); + qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } @@ -73,7 +73,7 @@ int findEyeLast = timer.elapsed(); qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); -// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.matData = cv::imread("/home/casic/code/irisLogs/145333.552.bmp", 0); // irisInfo.hasEye = true; // 4.1 没有找到眼睛则返回 @@ -117,11 +117,10 @@ // 缩放到320 * 240 cv::resize(segMat, segMat, cv::Size(SettingConfig::getInstance().IRIS_WIDTH * 0.5, SettingConfig::getInstance().IRIS_HEIGHT * 0.5)); - - // std::string filename = QString("%1\\%2\\%3-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - // cv::imwrite(filename, segMat); - // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - +/* + std::string filename = QString("%1/%2/%3-seg.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(filename, segMat); +*/ int segMatSize = segMat.cols * segMat.rows; QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 @@ -167,9 +166,9 @@ // 成功接收后清除缓存区 clientUtil->resetRecvBuffer(); /* - std::string pupilSeg = QString("%1\\%2\\%3-pupil-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string maskSeg = QString("%1\\%2\\%3-mask-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string irisSeg = QString("%1\\%2\\%3-iris-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string pupilSeg = QString("%1/%2/%3-pupil-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); cv::imwrite(pupilSeg, pupil); cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); @@ -196,12 +195,20 @@ CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; irisInfo = casic::iris::CasicIrisInterface::getInstance().irisEncode(irisInfo); /* - std::string codeFilename = QString("%1\\%2\\%3-code.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string codeFilename = QString("%1/%2/%3-code.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string maskFilename = QString("%1/%2/%3-mask.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); */ + if (irisInfo.postProcSucc == false) { + qDebug() << "算法post process失败,暂停200ms"; + + addOneTryCount(); + this->msleep(THREAD_MSLEEP); // 200ms后再判断 + continue; + } + // 从编码中提取特征值 irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); @@ -211,6 +218,8 @@ CasicIrisRecState::getInstance().extractTmLast = encodeLast; CasicIrisRecState::getInstance().recogTimeLast += encodeLast; +// cv::imwrite(QString("%1/%2/%3.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(), irisInfo.matData); + // 开始匹配 timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) @@ -219,7 +228,7 @@ float score = casic::iris::CasicIrisInterface::getInstance().calculatePairPoints(feature.irisFeatureCode, irisInfo.irisFeatureCode); // 计算压缩编码的比较值 -// cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); +// cv::imwrite(QString("%1/%2/%3-%4.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; @@ -251,7 +260,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } @@ -268,7 +277,7 @@ CasicIrisRecState::getInstance().tryCount = 0; this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); emit failedMatchedIris(); @@ -290,7 +299,7 @@ // 识别失败时暂停工作 待返回识别界面时再开始工作和拍图 this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); } } else if (ProMemory::getInstance().appState == AppConstants::ApplicationState::STATE_WORKING) @@ -298,7 +307,8 @@ CasicIrisRecState::getInstance().noEyeCount++; // 如果在工作状态 则超过一定次数后返回待机 - if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT) + if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT && + SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT > 0) { // 发送信号待机 emit backToLockScreen(); diff --git a/device/iris/IrisRecogProcess.h b/device/iris/IrisRecogProcess.h index 9a3eec6..e21c1a7 100644 --- a/device/iris/IrisRecogProcess.h +++ b/device/iris/IrisRecogProcess.h @@ -1,4 +1,4 @@ -#ifndef IRISRECOGPROCESS_H +#ifndef IRISRECOGPROCESS_H #define IRISRECOGPROCESS_H #define THREAD_MSLEEP 200 @@ -10,6 +10,7 @@ #include "ProMemory.h" #include "device/iris/CasicIrisRecState.h" +#include "casic/iris/CasicIrisInterface.h" class IrisRecogProcess : public QThread { diff --git a/main.cpp b/main.cpp index 9052ddb..3bfb1c6 100644 --- a/main.cpp +++ b/main.cpp @@ -1,11 +1,11 @@ -#include "MainWindowForm.h" - -#include - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - MainWindowForm w; - w.show(); - return a.exec(); -} +#include "MainWindowForm.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindowForm w; + w.show(); + return a.exec(); +} diff --git a/utils/ImageUtil.cpp b/utils/ImageUtil.cpp index ff77331..d40ea79 100644 --- a/utils/ImageUtil.cpp +++ b/utils/ImageUtil.cpp @@ -1,107 +1,107 @@ -#include "ImageUtil.h" - -ImageUtil::ImageUtil() -{ - -} - -QImage ImageUtil::MatImageToQImage(const cv::Mat &src) -{ - //CV_8UC1 8位无符号的单通道---灰度图片 - if(src.type() == CV_8UC1) - { - QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); - return qImage; - } - //为3通道的彩色图片 - else if(src.type() == CV_8UC3) - { - //得到图像的的首地址 - const uchar *pSrc = (const uchar*)src.data; - //以src构造图片 - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); - } - //四通道图片, 带Alpha通道的RGB彩色图像 - else if(src.type() == CV_8UC4) - { - const uchar *pSrc = (const uchar*)src.data; - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); - //返回图像的子区域作为一个新图像 - return qImage.copy(); - } - else - { - return QImage(); - } -} - -cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) -{ - cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); - return img; -} - -cv::Mat ImageUtil::QImageToMat(QImage image) -{ - cv::Mat mat; - switch(image.format()) - { - case QImage::Format_ARGB32: - case QImage::Format_RGB32: - case QImage::Format_ARGB32_Premultiplied: - mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_RGB888: - mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); - cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); - break; - case QImage::Format_Indexed8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_Grayscale8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); - break; - - default: - break; - } - - mat = mat.clone(); - - return mat; -} - -/* -QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) -{ - QImage qImage(data, width, height, format); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); -} - -QString ImageUtil::QImageToBase64(QImage image) -{ - QByteArray ba; - QBuffer buf(&ba); - image.save(&buf, "bmp"); - QString base64String = ba.toBase64(); - return base64String; -} - -cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) -{ - cv::Mat matClone = src.clone(); - cv::Rect bigRect; - - bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; - bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; - bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; - bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; - - cv::Mat roi = matClone(bigRect); - - return roi; -} -*/ +#include "ImageUtil.h" + +ImageUtil::ImageUtil() +{ + +} + +QImage ImageUtil::MatImageToQImage(const cv::Mat &src) +{ + //CV_8UC1 8位无符号的单通道---灰度图片 + if(src.type() == CV_8UC1) + { + QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); + return qImage; + } + //为3通道的彩色图片 + else if(src.type() == CV_8UC3) + { + //得到图像的的首地址 + const uchar *pSrc = (const uchar*)src.data; + //以src构造图片 + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); + } + //四通道图片, 带Alpha通道的RGB彩色图像 + else if(src.type() == CV_8UC4) + { + const uchar *pSrc = (const uchar*)src.data; + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); + //返回图像的子区域作为一个新图像 + return qImage.copy(); + } + else + { + return QImage(); + } +} + +cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) +{ + cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); + return img; +} + +cv::Mat ImageUtil::QImageToMat(QImage image) +{ + cv::Mat mat; + switch(image.format()) + { + case QImage::Format_ARGB32: + case QImage::Format_RGB32: + case QImage::Format_ARGB32_Premultiplied: + mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_RGB888: + mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); + cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); + break; + case QImage::Format_Indexed8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_Grayscale8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); + break; + + default: + break; + } + + mat = mat.clone(); + + return mat; +} + +/* +QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) +{ + QImage qImage(data, width, height, format); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); +} + +QString ImageUtil::QImageToBase64(QImage image) +{ + QByteArray ba; + QBuffer buf(&ba); + image.save(&buf, "bmp"); + QString base64String = ba.toBase64(); + return base64String; +} + +cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) +{ + cv::Mat matClone = src.clone(); + cv::Rect bigRect; + + bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; + bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; + bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; + bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; + + cv::Mat roi = matClone(bigRect); + + return roi; +} +*/ diff --git a/utils/ImageUtil.h b/utils/ImageUtil.h index d9bf00a..4b702f4 100644 --- a/utils/ImageUtil.h +++ b/utils/ImageUtil.h @@ -1,23 +1,23 @@ -#ifndef IMAGEUTIL_H -#define IMAGEUTIL_H - -#include -#include -#include "opencv2/opencv.hpp" - -class ImageUtil -{ -public: - ImageUtil(); - - static QImage MatImageToQImage(const cv::Mat &src); -// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); - - static cv::Mat ucharToMat(unsigned char * data, int row, int col); - static cv::Mat QImageToMat(QImage image); -// static QString QImageToBase64(QImage image); - -// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); -}; - -#endif // IMAGEUTIL_H +#ifndef IMAGEUTIL_H +#define IMAGEUTIL_H + +#include +#include +#include "opencv2/opencv.hpp" + +class ImageUtil +{ +public: + ImageUtil(); + + static QImage MatImageToQImage(const cv::Mat &src); +// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); + + static cv::Mat ucharToMat(unsigned char * data, int row, int col); + static cv::Mat QImageToMat(QImage image); +// static QString QImageToBase64(QImage image); + +// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); +}; + +#endif // IMAGEUTIL_H diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp index 663db0f..05c4c68 100644 --- a/utils/SettingConfig.cpp +++ b/utils/SettingConfig.cpp @@ -1,4 +1,4 @@ -#include "SettingConfig.h" +#include "SettingConfig.h" #include SettingConfig::SettingConfig() @@ -34,6 +34,9 @@ LOG_FILE = getProperty("log", "logFile").toString(); LOG_LEVEL = getProperty("log", "logLevel").toString(); + + DEBUG_CAMERA_ROTATE = getProperty("debug", "cameraRotate").toString(); + DEBUG_SEGMENT_IP = getProperty("debug", "segmentIp").toString(); } diff --git a/utils/SettingConfig.h b/utils/SettingConfig.h index b65f553..c35d6ab 100644 --- a/utils/SettingConfig.h +++ b/utils/SettingConfig.h @@ -1,4 +1,4 @@ -#ifndef SETTINGCONFIG_H +#ifndef SETTINGCONFIG_H #define SETTINGCONFIG_H #include @@ -55,6 +55,9 @@ QString LOG_FILE; QString LOG_LEVEL; + QString DEBUG_CAMERA_ROTATE; + QString DEBUG_SEGMENT_IP; + private: SettingConfig(); diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/device/IrisCameraCapEventHandler.h b/device/IrisCameraCapEventHandler.h index 8b976c5..94f5594 100644 --- a/device/IrisCameraCapEventHandler.h +++ b/device/IrisCameraCapEventHandler.h @@ -1,10 +1,9 @@ -#ifndef IRISCAMERACAPEVENTHANDLER_H +#ifndef IRISCAMERACAPEVENTHANDLER_H #define IRISCAMERACAPEVENTHANDLER_H #include #include -#include "include/opencv2/opencv.hpp" -#include "include/daheng/GalaxyIncludes.h" +#include #include "casic/iris/CasicIrisInterface.h" #include "ProMemory.h" diff --git a/device/IrisCameraController.cpp b/device/IrisCameraController.cpp index 0928176..4eea013 100644 --- a/device/IrisCameraController.cpp +++ b/device/IrisCameraController.cpp @@ -1,8 +1,8 @@ -#include "IrisCameraController.h" +#include "IrisCameraController.h" IrisCameraController::IrisCameraController(QObject *parent) : QObject(parent) { - this->irisCamHandler = new IrisCameraCapEventHandler(this); + initIrisCameraController(); } IrisCameraController::~IrisCameraController() { @@ -10,101 +10,204 @@ } -void IrisCameraController::initIrisCamera() +void IrisCameraController::initIrisCameraController() { - IGXFactory::GetInstance().Init(); + // Init GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXInitLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraInitError(); + LOG_ERROR("[CameraController]初始化虹膜相机失败"); + return ; + } + LOG_INFO("[CameraController]初始化虹膜相机成功"); //枚举设备 - IGXFactory::GetInstance().UpdateDeviceList(1000, irisCamList); - - this->OpenDevice(); + UpdateDeviceList(); } void IrisCameraController::openIrisCamera() { - //设置Buffer处理模式 - irisStreamFeaturePtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst"); + GX_STATUS emStatus = GX_STATUS_SUCCESS; - //注册回调函数 - irisStreamPtr->RegisterCaptureCallback(irisCamHandler, &irisCamPtr); + if (m_ui32DeviceNum > 0) { + emStatus = GXOpenDeviceByIndex(1, &m_hDevice); - //开启流层通道 - irisStreamPtr->StartGrab(); + if (emStatus == GX_STATUS_SUCCESS) { + LOG_INFO("[CameraController]开启虹膜相机成功"); - //发送开采命令 - irisFeaturePtr->GetCommandFeature("AcquisitionStart")->Execute(); + // isOpen flag set true + m_bOpen = true; - // 启动定时器 - TimeCounterUtil::getInstance().irisCapCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); // 50ms执行一次定时器 + SetUpAcquisitionThread(); + } + } + + return; } void IrisCameraController::closeIrisCamera() { - + // Release GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXCloseLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraTermError(); + } } void IrisCameraController::startCapture() { // 获取定时器, 绑定定时函数 - connect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString()); + bool bSetDone = false; + // Set acquisition buffer number + bSetDone = SetAcquisitionBufferNum(); + if (!bSetDone) + { + return; + } + + bool bPrepareDone = false; + // Alloc resource for image acquisition + bPrepareDone = m_pobjAcqThread->PrepareForShowImg(); + if (!bPrepareDone) + { + return; + } + + // Device start acquisition and start acquisition thread + StartAcquisition(); + + LOG_DEBUG(QString("[CameraController][startCapture]虹膜相机拍图").toStdString()); + + // Do not start timer when acquisition start failed + if (!m_bAcquisitionStart) + { + return; + } } void IrisCameraController::stopCapture() { - // 获取定时器, 绑定定时函数 - disconnect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString()); - + this->StopAcquisition(); } -void IrisCameraController::getOneFaceFrm() +void IrisCameraController::SetUpAcquisitionThread() { - // 发送软触发命令(在触发模式开启时有效) - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::getLeftAndRightEyeFrame() -{ - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::OpenDevice() -{ - auto device = irisCamList.at(0); - - irisCamPtr = IGXFactory::GetInstance().OpenDeviceByUserID(device.GetUserID(), GX_ACCESS_EXCLUSIVE); - irisFeaturePtr = irisCamPtr->GetRemoteFeatureControl(); - - // 判断设备流是否大于零, 如果大于零则打开流 - int nStreamCount = irisCamPtr->GetStreamCount(); - if (nStreamCount > 0) + // if Acquisition thread is on Stop acquisition thread + if (m_pobjAcqThread != NULL) { - irisStreamPtr = irisCamPtr->OpenStream(0); - irisStreamFeaturePtr = irisStreamPtr->GetFeatureControl(); + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Release acquisition thread object + RELEASE_ALLOC_MEM(m_pobjAcqThread); } - // 建议用户在打开网络相机之后, 根据当前网络环境设置相机的流通道包长值, - // 以提高网络相机的采集性能, 设置方法参考以下代码。 - GX_DEVICE_CLASS_LIST objDeviceClass = irisCamPtr->GetDeviceInfo().GetDeviceClass(); - if(GX_DEVICE_CLASS_GEV == objDeviceClass) + // Instantiation acquisition thread + try { - // 判断设备是否支持流通道数据包功能 - if(true == irisFeaturePtr->IsImplemented("GevSCPSPacketSize")) - { - // 获取当前网络环境的最优包长值 - int nPacketSize = irisStreamPtr->GetOptimalPacketSize(); - // 将最优包长值设置为当前设备的流通道包长值 - irisFeaturePtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize); - } + m_pobjAcqThread = new CAcquisitionThread(); + m_pobjAcqThread->m_hDevice = m_hDevice; + } + catch (std::bad_alloc &e) + { + QMessageBox::about(NULL, "Allocate memory error", "Cannot allocate memory, please exit this app!"); + RELEASE_ALLOC_MEM(m_pobjAcqThread); + return; } - //设置采集模式为连续采集模式 - irisFeaturePtr->GetEnumFeature("AcquisitionMode")->SetValue("Continuous"); + return; +} - //设置触发模式关 - irisFeaturePtr->GetEnumFeature("TriggerMode")->SetValue("On"); - irisFeaturePtr->GetEnumFeature("TriggerSource")->SetValue("Software"); +void IrisCameraController::UpdateDeviceList() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Enumerate Devcie List + emStatus = GXUpdateDeviceList(&m_ui32DeviceNum, ENUMRATE_TIME_OUT); + + LOG_INFO(QString("[CameraController]枚举虹膜相机成功[%1]").arg(m_ui32DeviceNum).toStdString()); + + return; +} + +void IrisCameraController::StartAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + emStatus = GXStreamOn(m_hDevice); + + // Set acquisition thread run flag + m_pobjAcqThread->m_bAcquisitionThreadFlag = true; + + // Acquisition thread start + m_pobjAcqThread->start(); + + // isStart flag set true + m_bAcquisitionStart = true; + + return; +} + +void IrisCameraController::StopAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Turn off stream + emStatus = GXStreamOff(m_hDevice); + + // isStart flag set false + m_bAcquisitionStart = false; + + return; +} + +bool IrisCameraController::SetAcquisitionBufferNum() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + uint64_t ui64BufferNum = 0; + int64_t i64PayloadSize = 0; + + // Get device current payload size + emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &i64PayloadSize); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Set buffer quantity of acquisition queue + if (i64PayloadSize == 0) + { + return false; + } + + // Calculate a reasonable number of Buffers for different payload size + // Small ROI and high frame rate will requires more acquisition Buffer + const size_t MAX_MEMORY_SIZE = 8 * 1024 * 1024; // The maximum number of memory bytes available for allocating frame Buffer + const size_t MIN_BUFFER_NUM = 5; // Minimum frame Buffer number + const size_t MAX_BUFFER_NUM = 450; // Maximum frame Buffer number + ui64BufferNum = MAX_MEMORY_SIZE / i64PayloadSize; + ui64BufferNum = (ui64BufferNum <= MIN_BUFFER_NUM) ? MIN_BUFFER_NUM : ui64BufferNum; + ui64BufferNum = (ui64BufferNum >= MAX_BUFFER_NUM) ? MAX_BUFFER_NUM : ui64BufferNum; + + emStatus = GXSetAcqusitionBufferNumber(m_hDevice, ui64BufferNum); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Transfer buffer number to acquisition thread class for using GXDQAllBufs + m_pobjAcqThread->m_ui64AcquisitionBufferNum = ui64BufferNum; + + return true; } diff --git a/device/IrisCameraController.h b/device/IrisCameraController.h index 5d7e269..67cbe2f 100644 --- a/device/IrisCameraController.h +++ b/device/IrisCameraController.h @@ -1,11 +1,12 @@ -#ifndef IRISCAMERACONTROLLER_H +#ifndef IRISCAMERACONTROLLER_H #define IRISCAMERACONTROLLER_H #include -#include "IrisCameraCapEventHandler.h" +#include "AcquisitionThread.h" +#include "utils/UtilInclude.h" -class IrisCameraCapEventHandler; +#define ENUMRATE_TIME_OUT 200 class IrisCameraController : public QObject { @@ -14,36 +15,31 @@ explicit IrisCameraController(QObject *parent = nullptr); ~IrisCameraController(); - // 初始化并打开人脸相机 - void initIrisCamera(); void openIrisCamera(); void closeIrisCamera(); void startCapture(); void stopCapture(); - void getLeftAndRightEyeFrame(); + CAcquisitionThread * m_pobjAcqThread; + GX_DEV_HANDLE m_hDevice; ///< Device Handle + uint32_t m_ui32DeviceNum; ///< Device number enumerated - IrisCameraCapEventHandler * irisCamHandler; + bool m_bOpen; ///< Flag : camera is opened or not + bool m_bAcquisitionStart; ///< Flag : camera is acquiring or not private: - GxIAPICPP::gxdeviceinfo_vector irisCamList; - - CGXDevicePointer irisCamPtr; ///< 设备句柄 - - CGXStreamPointer irisStreamPtr; ///< 左眼设备流 - - CGXFeatureControlPointer irisFeaturePtr; ///< 左眼属性控制器 - - CGXFeatureControlPointer irisStreamFeaturePtr; ///< 左眼流层控制器对象 - - void OpenDevice(); + // 初始化并打开人脸相机 + void initIrisCameraController(); + void SetUpAcquisitionThread(); + void UpdateDeviceList(); + bool SetAcquisitionBufferNum(); + void StartAcquisition(); + void StopAcquisition(); signals: - -public slots: - void getOneFaceFrm(); - + void irisCameraInitError(); + void irisCameraTermError(); }; #endif // IRISCAMERACONTROLLER_H diff --git a/device/device.pri b/device/device.pri index d1330a0..583721b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,13 +1,14 @@ HEADERS += $$PWD/IrisCameraController.h -HEADERS += $$PWD/IrisCameraCapEventHandler.h -#HEADERS += $$PWD/iris/IrisRegistProcess.h +#HEADERS += $$PWD/IrisCameraCapEventHandler.h +HEADERS += $$PWD/Common.h +HEADERS += $$PWD/AcquisitionThread.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h SOURCES += $$PWD/IrisCameraController.cpp -SOURCES += $$PWD/IrisCameraCapEventHandler.cpp -#SOURCES += $$PWD/iris/IrisRegistProcess.cpp +#SOURCES += $$PWD/IrisCameraCapEventHandler.cpp +SOURCES += $$PWD/AcquisitionThread.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 38f54fe..e4c8a02 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -11,7 +11,7 @@ // 连接算法服务 clientUtil = new SocketClientUtil(this); - clientUtil->connect("192.168.83.223", 50007); + clientUtil->connect(SettingConfig::getInstance().DEBUG_SEGMENT_IP, 50007); // 调用socket发送消息 connect(this, &IrisRecogProcess::sendDataToExract, clientUtil, &SocketClientUtil::sendData); @@ -43,18 +43,18 @@ continue; } - // 1. 图像栈中没有图像则直接返回 - if (ProMemory::getInstance().isIrisQueueEmpty() == true) + // 1. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 + if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) { - qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); + qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } - // 2. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 - if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) + // 2. 图像栈中没有图像则直接返回 + if (ProMemory::getInstance().isIrisQueueEmpty() == true) { - qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); + qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } @@ -73,7 +73,7 @@ int findEyeLast = timer.elapsed(); qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); -// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.matData = cv::imread("/home/casic/code/irisLogs/145333.552.bmp", 0); // irisInfo.hasEye = true; // 4.1 没有找到眼睛则返回 @@ -117,11 +117,10 @@ // 缩放到320 * 240 cv::resize(segMat, segMat, cv::Size(SettingConfig::getInstance().IRIS_WIDTH * 0.5, SettingConfig::getInstance().IRIS_HEIGHT * 0.5)); - - // std::string filename = QString("%1\\%2\\%3-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - // cv::imwrite(filename, segMat); - // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - +/* + std::string filename = QString("%1/%2/%3-seg.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(filename, segMat); +*/ int segMatSize = segMat.cols * segMat.rows; QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 @@ -167,9 +166,9 @@ // 成功接收后清除缓存区 clientUtil->resetRecvBuffer(); /* - std::string pupilSeg = QString("%1\\%2\\%3-pupil-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string maskSeg = QString("%1\\%2\\%3-mask-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string irisSeg = QString("%1\\%2\\%3-iris-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string pupilSeg = QString("%1/%2/%3-pupil-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); cv::imwrite(pupilSeg, pupil); cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); @@ -196,12 +195,20 @@ CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; irisInfo = casic::iris::CasicIrisInterface::getInstance().irisEncode(irisInfo); /* - std::string codeFilename = QString("%1\\%2\\%3-code.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string codeFilename = QString("%1/%2/%3-code.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string maskFilename = QString("%1/%2/%3-mask.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); */ + if (irisInfo.postProcSucc == false) { + qDebug() << "算法post process失败,暂停200ms"; + + addOneTryCount(); + this->msleep(THREAD_MSLEEP); // 200ms后再判断 + continue; + } + // 从编码中提取特征值 irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); @@ -211,6 +218,8 @@ CasicIrisRecState::getInstance().extractTmLast = encodeLast; CasicIrisRecState::getInstance().recogTimeLast += encodeLast; +// cv::imwrite(QString("%1/%2/%3.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(), irisInfo.matData); + // 开始匹配 timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) @@ -219,7 +228,7 @@ float score = casic::iris::CasicIrisInterface::getInstance().calculatePairPoints(feature.irisFeatureCode, irisInfo.irisFeatureCode); // 计算压缩编码的比较值 -// cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); +// cv::imwrite(QString("%1/%2/%3-%4.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; @@ -251,7 +260,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } @@ -268,7 +277,7 @@ CasicIrisRecState::getInstance().tryCount = 0; this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); emit failedMatchedIris(); @@ -290,7 +299,7 @@ // 识别失败时暂停工作 待返回识别界面时再开始工作和拍图 this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); } } else if (ProMemory::getInstance().appState == AppConstants::ApplicationState::STATE_WORKING) @@ -298,7 +307,8 @@ CasicIrisRecState::getInstance().noEyeCount++; // 如果在工作状态 则超过一定次数后返回待机 - if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT) + if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT && + SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT > 0) { // 发送信号待机 emit backToLockScreen(); diff --git a/device/iris/IrisRecogProcess.h b/device/iris/IrisRecogProcess.h index 9a3eec6..e21c1a7 100644 --- a/device/iris/IrisRecogProcess.h +++ b/device/iris/IrisRecogProcess.h @@ -1,4 +1,4 @@ -#ifndef IRISRECOGPROCESS_H +#ifndef IRISRECOGPROCESS_H #define IRISRECOGPROCESS_H #define THREAD_MSLEEP 200 @@ -10,6 +10,7 @@ #include "ProMemory.h" #include "device/iris/CasicIrisRecState.h" +#include "casic/iris/CasicIrisInterface.h" class IrisRecogProcess : public QThread { diff --git a/main.cpp b/main.cpp index 9052ddb..3bfb1c6 100644 --- a/main.cpp +++ b/main.cpp @@ -1,11 +1,11 @@ -#include "MainWindowForm.h" - -#include - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - MainWindowForm w; - w.show(); - return a.exec(); -} +#include "MainWindowForm.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindowForm w; + w.show(); + return a.exec(); +} diff --git a/utils/ImageUtil.cpp b/utils/ImageUtil.cpp index ff77331..d40ea79 100644 --- a/utils/ImageUtil.cpp +++ b/utils/ImageUtil.cpp @@ -1,107 +1,107 @@ -#include "ImageUtil.h" - -ImageUtil::ImageUtil() -{ - -} - -QImage ImageUtil::MatImageToQImage(const cv::Mat &src) -{ - //CV_8UC1 8位无符号的单通道---灰度图片 - if(src.type() == CV_8UC1) - { - QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); - return qImage; - } - //为3通道的彩色图片 - else if(src.type() == CV_8UC3) - { - //得到图像的的首地址 - const uchar *pSrc = (const uchar*)src.data; - //以src构造图片 - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); - } - //四通道图片, 带Alpha通道的RGB彩色图像 - else if(src.type() == CV_8UC4) - { - const uchar *pSrc = (const uchar*)src.data; - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); - //返回图像的子区域作为一个新图像 - return qImage.copy(); - } - else - { - return QImage(); - } -} - -cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) -{ - cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); - return img; -} - -cv::Mat ImageUtil::QImageToMat(QImage image) -{ - cv::Mat mat; - switch(image.format()) - { - case QImage::Format_ARGB32: - case QImage::Format_RGB32: - case QImage::Format_ARGB32_Premultiplied: - mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_RGB888: - mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); - cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); - break; - case QImage::Format_Indexed8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_Grayscale8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); - break; - - default: - break; - } - - mat = mat.clone(); - - return mat; -} - -/* -QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) -{ - QImage qImage(data, width, height, format); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); -} - -QString ImageUtil::QImageToBase64(QImage image) -{ - QByteArray ba; - QBuffer buf(&ba); - image.save(&buf, "bmp"); - QString base64String = ba.toBase64(); - return base64String; -} - -cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) -{ - cv::Mat matClone = src.clone(); - cv::Rect bigRect; - - bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; - bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; - bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; - bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; - - cv::Mat roi = matClone(bigRect); - - return roi; -} -*/ +#include "ImageUtil.h" + +ImageUtil::ImageUtil() +{ + +} + +QImage ImageUtil::MatImageToQImage(const cv::Mat &src) +{ + //CV_8UC1 8位无符号的单通道---灰度图片 + if(src.type() == CV_8UC1) + { + QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); + return qImage; + } + //为3通道的彩色图片 + else if(src.type() == CV_8UC3) + { + //得到图像的的首地址 + const uchar *pSrc = (const uchar*)src.data; + //以src构造图片 + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); + } + //四通道图片, 带Alpha通道的RGB彩色图像 + else if(src.type() == CV_8UC4) + { + const uchar *pSrc = (const uchar*)src.data; + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); + //返回图像的子区域作为一个新图像 + return qImage.copy(); + } + else + { + return QImage(); + } +} + +cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) +{ + cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); + return img; +} + +cv::Mat ImageUtil::QImageToMat(QImage image) +{ + cv::Mat mat; + switch(image.format()) + { + case QImage::Format_ARGB32: + case QImage::Format_RGB32: + case QImage::Format_ARGB32_Premultiplied: + mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_RGB888: + mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); + cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); + break; + case QImage::Format_Indexed8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_Grayscale8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); + break; + + default: + break; + } + + mat = mat.clone(); + + return mat; +} + +/* +QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) +{ + QImage qImage(data, width, height, format); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); +} + +QString ImageUtil::QImageToBase64(QImage image) +{ + QByteArray ba; + QBuffer buf(&ba); + image.save(&buf, "bmp"); + QString base64String = ba.toBase64(); + return base64String; +} + +cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) +{ + cv::Mat matClone = src.clone(); + cv::Rect bigRect; + + bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; + bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; + bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; + bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; + + cv::Mat roi = matClone(bigRect); + + return roi; +} +*/ diff --git a/utils/ImageUtil.h b/utils/ImageUtil.h index d9bf00a..4b702f4 100644 --- a/utils/ImageUtil.h +++ b/utils/ImageUtil.h @@ -1,23 +1,23 @@ -#ifndef IMAGEUTIL_H -#define IMAGEUTIL_H - -#include -#include -#include "opencv2/opencv.hpp" - -class ImageUtil -{ -public: - ImageUtil(); - - static QImage MatImageToQImage(const cv::Mat &src); -// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); - - static cv::Mat ucharToMat(unsigned char * data, int row, int col); - static cv::Mat QImageToMat(QImage image); -// static QString QImageToBase64(QImage image); - -// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); -}; - -#endif // IMAGEUTIL_H +#ifndef IMAGEUTIL_H +#define IMAGEUTIL_H + +#include +#include +#include "opencv2/opencv.hpp" + +class ImageUtil +{ +public: + ImageUtil(); + + static QImage MatImageToQImage(const cv::Mat &src); +// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); + + static cv::Mat ucharToMat(unsigned char * data, int row, int col); + static cv::Mat QImageToMat(QImage image); +// static QString QImageToBase64(QImage image); + +// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); +}; + +#endif // IMAGEUTIL_H diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp index 663db0f..05c4c68 100644 --- a/utils/SettingConfig.cpp +++ b/utils/SettingConfig.cpp @@ -1,4 +1,4 @@ -#include "SettingConfig.h" +#include "SettingConfig.h" #include SettingConfig::SettingConfig() @@ -34,6 +34,9 @@ LOG_FILE = getProperty("log", "logFile").toString(); LOG_LEVEL = getProperty("log", "logLevel").toString(); + + DEBUG_CAMERA_ROTATE = getProperty("debug", "cameraRotate").toString(); + DEBUG_SEGMENT_IP = getProperty("debug", "segmentIp").toString(); } diff --git a/utils/SettingConfig.h b/utils/SettingConfig.h index b65f553..c35d6ab 100644 --- a/utils/SettingConfig.h +++ b/utils/SettingConfig.h @@ -1,4 +1,4 @@ -#ifndef SETTINGCONFIG_H +#ifndef SETTINGCONFIG_H #define SETTINGCONFIG_H #include @@ -55,6 +55,9 @@ QString LOG_FILE; QString LOG_LEVEL; + QString DEBUG_CAMERA_ROTATE; + QString DEBUG_SEGMENT_IP; + private: SettingConfig(); diff --git a/utils/SocketClientUtil.cpp b/utils/SocketClientUtil.cpp index d539d64..20b8869 100644 --- a/utils/SocketClientUtil.cpp +++ b/utils/SocketClientUtil.cpp @@ -1,9 +1,10 @@ -#include "SocketClientUtil.h" +#include "SocketClientUtil.h" #include "utils/ByteUtil.h" SocketClientUtil::SocketClientUtil(QObject *parent) : QObject(parent) { QObject::connect(&objClient, &QTcpSocket::readyRead, this, &SocketClientUtil::readData); + QObject::connect(&objClient, &QTcpSocket::disconnected, this, &SocketClientUtil::socketReconnect); } void SocketClientUtil::connect(QString host, int port) @@ -16,6 +17,10 @@ void SocketClientUtil::closeConnect() { + QObject::disconnect(&objClient, &QTcpSocket::readyRead, this, &SocketClientUtil::readData); + QObject::disconnect(&objClient, &QTcpSocket::disconnected, this, &SocketClientUtil::socketReconnect); + + objClient.disconnectFromHost(); objClient.close(); } @@ -45,3 +50,9 @@ emit this->responseReaded(); } } + +void SocketClientUtil::socketReconnect() +{ + objClient.close(); + objClient.connectToHost(this->host, this->port); +} diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/device/IrisCameraCapEventHandler.h b/device/IrisCameraCapEventHandler.h index 8b976c5..94f5594 100644 --- a/device/IrisCameraCapEventHandler.h +++ b/device/IrisCameraCapEventHandler.h @@ -1,10 +1,9 @@ -#ifndef IRISCAMERACAPEVENTHANDLER_H +#ifndef IRISCAMERACAPEVENTHANDLER_H #define IRISCAMERACAPEVENTHANDLER_H #include #include -#include "include/opencv2/opencv.hpp" -#include "include/daheng/GalaxyIncludes.h" +#include #include "casic/iris/CasicIrisInterface.h" #include "ProMemory.h" diff --git a/device/IrisCameraController.cpp b/device/IrisCameraController.cpp index 0928176..4eea013 100644 --- a/device/IrisCameraController.cpp +++ b/device/IrisCameraController.cpp @@ -1,8 +1,8 @@ -#include "IrisCameraController.h" +#include "IrisCameraController.h" IrisCameraController::IrisCameraController(QObject *parent) : QObject(parent) { - this->irisCamHandler = new IrisCameraCapEventHandler(this); + initIrisCameraController(); } IrisCameraController::~IrisCameraController() { @@ -10,101 +10,204 @@ } -void IrisCameraController::initIrisCamera() +void IrisCameraController::initIrisCameraController() { - IGXFactory::GetInstance().Init(); + // Init GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXInitLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraInitError(); + LOG_ERROR("[CameraController]初始化虹膜相机失败"); + return ; + } + LOG_INFO("[CameraController]初始化虹膜相机成功"); //枚举设备 - IGXFactory::GetInstance().UpdateDeviceList(1000, irisCamList); - - this->OpenDevice(); + UpdateDeviceList(); } void IrisCameraController::openIrisCamera() { - //设置Buffer处理模式 - irisStreamFeaturePtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst"); + GX_STATUS emStatus = GX_STATUS_SUCCESS; - //注册回调函数 - irisStreamPtr->RegisterCaptureCallback(irisCamHandler, &irisCamPtr); + if (m_ui32DeviceNum > 0) { + emStatus = GXOpenDeviceByIndex(1, &m_hDevice); - //开启流层通道 - irisStreamPtr->StartGrab(); + if (emStatus == GX_STATUS_SUCCESS) { + LOG_INFO("[CameraController]开启虹膜相机成功"); - //发送开采命令 - irisFeaturePtr->GetCommandFeature("AcquisitionStart")->Execute(); + // isOpen flag set true + m_bOpen = true; - // 启动定时器 - TimeCounterUtil::getInstance().irisCapCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); // 50ms执行一次定时器 + SetUpAcquisitionThread(); + } + } + + return; } void IrisCameraController::closeIrisCamera() { - + // Release GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXCloseLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraTermError(); + } } void IrisCameraController::startCapture() { // 获取定时器, 绑定定时函数 - connect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString()); + bool bSetDone = false; + // Set acquisition buffer number + bSetDone = SetAcquisitionBufferNum(); + if (!bSetDone) + { + return; + } + + bool bPrepareDone = false; + // Alloc resource for image acquisition + bPrepareDone = m_pobjAcqThread->PrepareForShowImg(); + if (!bPrepareDone) + { + return; + } + + // Device start acquisition and start acquisition thread + StartAcquisition(); + + LOG_DEBUG(QString("[CameraController][startCapture]虹膜相机拍图").toStdString()); + + // Do not start timer when acquisition start failed + if (!m_bAcquisitionStart) + { + return; + } } void IrisCameraController::stopCapture() { - // 获取定时器, 绑定定时函数 - disconnect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString()); - + this->StopAcquisition(); } -void IrisCameraController::getOneFaceFrm() +void IrisCameraController::SetUpAcquisitionThread() { - // 发送软触发命令(在触发模式开启时有效) - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::getLeftAndRightEyeFrame() -{ - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::OpenDevice() -{ - auto device = irisCamList.at(0); - - irisCamPtr = IGXFactory::GetInstance().OpenDeviceByUserID(device.GetUserID(), GX_ACCESS_EXCLUSIVE); - irisFeaturePtr = irisCamPtr->GetRemoteFeatureControl(); - - // 判断设备流是否大于零, 如果大于零则打开流 - int nStreamCount = irisCamPtr->GetStreamCount(); - if (nStreamCount > 0) + // if Acquisition thread is on Stop acquisition thread + if (m_pobjAcqThread != NULL) { - irisStreamPtr = irisCamPtr->OpenStream(0); - irisStreamFeaturePtr = irisStreamPtr->GetFeatureControl(); + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Release acquisition thread object + RELEASE_ALLOC_MEM(m_pobjAcqThread); } - // 建议用户在打开网络相机之后, 根据当前网络环境设置相机的流通道包长值, - // 以提高网络相机的采集性能, 设置方法参考以下代码。 - GX_DEVICE_CLASS_LIST objDeviceClass = irisCamPtr->GetDeviceInfo().GetDeviceClass(); - if(GX_DEVICE_CLASS_GEV == objDeviceClass) + // Instantiation acquisition thread + try { - // 判断设备是否支持流通道数据包功能 - if(true == irisFeaturePtr->IsImplemented("GevSCPSPacketSize")) - { - // 获取当前网络环境的最优包长值 - int nPacketSize = irisStreamPtr->GetOptimalPacketSize(); - // 将最优包长值设置为当前设备的流通道包长值 - irisFeaturePtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize); - } + m_pobjAcqThread = new CAcquisitionThread(); + m_pobjAcqThread->m_hDevice = m_hDevice; + } + catch (std::bad_alloc &e) + { + QMessageBox::about(NULL, "Allocate memory error", "Cannot allocate memory, please exit this app!"); + RELEASE_ALLOC_MEM(m_pobjAcqThread); + return; } - //设置采集模式为连续采集模式 - irisFeaturePtr->GetEnumFeature("AcquisitionMode")->SetValue("Continuous"); + return; +} - //设置触发模式关 - irisFeaturePtr->GetEnumFeature("TriggerMode")->SetValue("On"); - irisFeaturePtr->GetEnumFeature("TriggerSource")->SetValue("Software"); +void IrisCameraController::UpdateDeviceList() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Enumerate Devcie List + emStatus = GXUpdateDeviceList(&m_ui32DeviceNum, ENUMRATE_TIME_OUT); + + LOG_INFO(QString("[CameraController]枚举虹膜相机成功[%1]").arg(m_ui32DeviceNum).toStdString()); + + return; +} + +void IrisCameraController::StartAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + emStatus = GXStreamOn(m_hDevice); + + // Set acquisition thread run flag + m_pobjAcqThread->m_bAcquisitionThreadFlag = true; + + // Acquisition thread start + m_pobjAcqThread->start(); + + // isStart flag set true + m_bAcquisitionStart = true; + + return; +} + +void IrisCameraController::StopAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Turn off stream + emStatus = GXStreamOff(m_hDevice); + + // isStart flag set false + m_bAcquisitionStart = false; + + return; +} + +bool IrisCameraController::SetAcquisitionBufferNum() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + uint64_t ui64BufferNum = 0; + int64_t i64PayloadSize = 0; + + // Get device current payload size + emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &i64PayloadSize); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Set buffer quantity of acquisition queue + if (i64PayloadSize == 0) + { + return false; + } + + // Calculate a reasonable number of Buffers for different payload size + // Small ROI and high frame rate will requires more acquisition Buffer + const size_t MAX_MEMORY_SIZE = 8 * 1024 * 1024; // The maximum number of memory bytes available for allocating frame Buffer + const size_t MIN_BUFFER_NUM = 5; // Minimum frame Buffer number + const size_t MAX_BUFFER_NUM = 450; // Maximum frame Buffer number + ui64BufferNum = MAX_MEMORY_SIZE / i64PayloadSize; + ui64BufferNum = (ui64BufferNum <= MIN_BUFFER_NUM) ? MIN_BUFFER_NUM : ui64BufferNum; + ui64BufferNum = (ui64BufferNum >= MAX_BUFFER_NUM) ? MAX_BUFFER_NUM : ui64BufferNum; + + emStatus = GXSetAcqusitionBufferNumber(m_hDevice, ui64BufferNum); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Transfer buffer number to acquisition thread class for using GXDQAllBufs + m_pobjAcqThread->m_ui64AcquisitionBufferNum = ui64BufferNum; + + return true; } diff --git a/device/IrisCameraController.h b/device/IrisCameraController.h index 5d7e269..67cbe2f 100644 --- a/device/IrisCameraController.h +++ b/device/IrisCameraController.h @@ -1,11 +1,12 @@ -#ifndef IRISCAMERACONTROLLER_H +#ifndef IRISCAMERACONTROLLER_H #define IRISCAMERACONTROLLER_H #include -#include "IrisCameraCapEventHandler.h" +#include "AcquisitionThread.h" +#include "utils/UtilInclude.h" -class IrisCameraCapEventHandler; +#define ENUMRATE_TIME_OUT 200 class IrisCameraController : public QObject { @@ -14,36 +15,31 @@ explicit IrisCameraController(QObject *parent = nullptr); ~IrisCameraController(); - // 初始化并打开人脸相机 - void initIrisCamera(); void openIrisCamera(); void closeIrisCamera(); void startCapture(); void stopCapture(); - void getLeftAndRightEyeFrame(); + CAcquisitionThread * m_pobjAcqThread; + GX_DEV_HANDLE m_hDevice; ///< Device Handle + uint32_t m_ui32DeviceNum; ///< Device number enumerated - IrisCameraCapEventHandler * irisCamHandler; + bool m_bOpen; ///< Flag : camera is opened or not + bool m_bAcquisitionStart; ///< Flag : camera is acquiring or not private: - GxIAPICPP::gxdeviceinfo_vector irisCamList; - - CGXDevicePointer irisCamPtr; ///< 设备句柄 - - CGXStreamPointer irisStreamPtr; ///< 左眼设备流 - - CGXFeatureControlPointer irisFeaturePtr; ///< 左眼属性控制器 - - CGXFeatureControlPointer irisStreamFeaturePtr; ///< 左眼流层控制器对象 - - void OpenDevice(); + // 初始化并打开人脸相机 + void initIrisCameraController(); + void SetUpAcquisitionThread(); + void UpdateDeviceList(); + bool SetAcquisitionBufferNum(); + void StartAcquisition(); + void StopAcquisition(); signals: - -public slots: - void getOneFaceFrm(); - + void irisCameraInitError(); + void irisCameraTermError(); }; #endif // IRISCAMERACONTROLLER_H diff --git a/device/device.pri b/device/device.pri index d1330a0..583721b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,13 +1,14 @@ HEADERS += $$PWD/IrisCameraController.h -HEADERS += $$PWD/IrisCameraCapEventHandler.h -#HEADERS += $$PWD/iris/IrisRegistProcess.h +#HEADERS += $$PWD/IrisCameraCapEventHandler.h +HEADERS += $$PWD/Common.h +HEADERS += $$PWD/AcquisitionThread.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h SOURCES += $$PWD/IrisCameraController.cpp -SOURCES += $$PWD/IrisCameraCapEventHandler.cpp -#SOURCES += $$PWD/iris/IrisRegistProcess.cpp +#SOURCES += $$PWD/IrisCameraCapEventHandler.cpp +SOURCES += $$PWD/AcquisitionThread.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 38f54fe..e4c8a02 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -11,7 +11,7 @@ // 连接算法服务 clientUtil = new SocketClientUtil(this); - clientUtil->connect("192.168.83.223", 50007); + clientUtil->connect(SettingConfig::getInstance().DEBUG_SEGMENT_IP, 50007); // 调用socket发送消息 connect(this, &IrisRecogProcess::sendDataToExract, clientUtil, &SocketClientUtil::sendData); @@ -43,18 +43,18 @@ continue; } - // 1. 图像栈中没有图像则直接返回 - if (ProMemory::getInstance().isIrisQueueEmpty() == true) + // 1. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 + if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) { - qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); + qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } - // 2. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 - if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) + // 2. 图像栈中没有图像则直接返回 + if (ProMemory::getInstance().isIrisQueueEmpty() == true) { - qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); + qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } @@ -73,7 +73,7 @@ int findEyeLast = timer.elapsed(); qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); -// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.matData = cv::imread("/home/casic/code/irisLogs/145333.552.bmp", 0); // irisInfo.hasEye = true; // 4.1 没有找到眼睛则返回 @@ -117,11 +117,10 @@ // 缩放到320 * 240 cv::resize(segMat, segMat, cv::Size(SettingConfig::getInstance().IRIS_WIDTH * 0.5, SettingConfig::getInstance().IRIS_HEIGHT * 0.5)); - - // std::string filename = QString("%1\\%2\\%3-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - // cv::imwrite(filename, segMat); - // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - +/* + std::string filename = QString("%1/%2/%3-seg.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(filename, segMat); +*/ int segMatSize = segMat.cols * segMat.rows; QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 @@ -167,9 +166,9 @@ // 成功接收后清除缓存区 clientUtil->resetRecvBuffer(); /* - std::string pupilSeg = QString("%1\\%2\\%3-pupil-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string maskSeg = QString("%1\\%2\\%3-mask-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string irisSeg = QString("%1\\%2\\%3-iris-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string pupilSeg = QString("%1/%2/%3-pupil-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); cv::imwrite(pupilSeg, pupil); cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); @@ -196,12 +195,20 @@ CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; irisInfo = casic::iris::CasicIrisInterface::getInstance().irisEncode(irisInfo); /* - std::string codeFilename = QString("%1\\%2\\%3-code.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string codeFilename = QString("%1/%2/%3-code.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string maskFilename = QString("%1/%2/%3-mask.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); */ + if (irisInfo.postProcSucc == false) { + qDebug() << "算法post process失败,暂停200ms"; + + addOneTryCount(); + this->msleep(THREAD_MSLEEP); // 200ms后再判断 + continue; + } + // 从编码中提取特征值 irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); @@ -211,6 +218,8 @@ CasicIrisRecState::getInstance().extractTmLast = encodeLast; CasicIrisRecState::getInstance().recogTimeLast += encodeLast; +// cv::imwrite(QString("%1/%2/%3.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(), irisInfo.matData); + // 开始匹配 timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) @@ -219,7 +228,7 @@ float score = casic::iris::CasicIrisInterface::getInstance().calculatePairPoints(feature.irisFeatureCode, irisInfo.irisFeatureCode); // 计算压缩编码的比较值 -// cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); +// cv::imwrite(QString("%1/%2/%3-%4.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; @@ -251,7 +260,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } @@ -268,7 +277,7 @@ CasicIrisRecState::getInstance().tryCount = 0; this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); emit failedMatchedIris(); @@ -290,7 +299,7 @@ // 识别失败时暂停工作 待返回识别界面时再开始工作和拍图 this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); } } else if (ProMemory::getInstance().appState == AppConstants::ApplicationState::STATE_WORKING) @@ -298,7 +307,8 @@ CasicIrisRecState::getInstance().noEyeCount++; // 如果在工作状态 则超过一定次数后返回待机 - if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT) + if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT && + SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT > 0) { // 发送信号待机 emit backToLockScreen(); diff --git a/device/iris/IrisRecogProcess.h b/device/iris/IrisRecogProcess.h index 9a3eec6..e21c1a7 100644 --- a/device/iris/IrisRecogProcess.h +++ b/device/iris/IrisRecogProcess.h @@ -1,4 +1,4 @@ -#ifndef IRISRECOGPROCESS_H +#ifndef IRISRECOGPROCESS_H #define IRISRECOGPROCESS_H #define THREAD_MSLEEP 200 @@ -10,6 +10,7 @@ #include "ProMemory.h" #include "device/iris/CasicIrisRecState.h" +#include "casic/iris/CasicIrisInterface.h" class IrisRecogProcess : public QThread { diff --git a/main.cpp b/main.cpp index 9052ddb..3bfb1c6 100644 --- a/main.cpp +++ b/main.cpp @@ -1,11 +1,11 @@ -#include "MainWindowForm.h" - -#include - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - MainWindowForm w; - w.show(); - return a.exec(); -} +#include "MainWindowForm.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindowForm w; + w.show(); + return a.exec(); +} diff --git a/utils/ImageUtil.cpp b/utils/ImageUtil.cpp index ff77331..d40ea79 100644 --- a/utils/ImageUtil.cpp +++ b/utils/ImageUtil.cpp @@ -1,107 +1,107 @@ -#include "ImageUtil.h" - -ImageUtil::ImageUtil() -{ - -} - -QImage ImageUtil::MatImageToQImage(const cv::Mat &src) -{ - //CV_8UC1 8位无符号的单通道---灰度图片 - if(src.type() == CV_8UC1) - { - QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); - return qImage; - } - //为3通道的彩色图片 - else if(src.type() == CV_8UC3) - { - //得到图像的的首地址 - const uchar *pSrc = (const uchar*)src.data; - //以src构造图片 - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); - } - //四通道图片, 带Alpha通道的RGB彩色图像 - else if(src.type() == CV_8UC4) - { - const uchar *pSrc = (const uchar*)src.data; - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); - //返回图像的子区域作为一个新图像 - return qImage.copy(); - } - else - { - return QImage(); - } -} - -cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) -{ - cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); - return img; -} - -cv::Mat ImageUtil::QImageToMat(QImage image) -{ - cv::Mat mat; - switch(image.format()) - { - case QImage::Format_ARGB32: - case QImage::Format_RGB32: - case QImage::Format_ARGB32_Premultiplied: - mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_RGB888: - mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); - cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); - break; - case QImage::Format_Indexed8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_Grayscale8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); - break; - - default: - break; - } - - mat = mat.clone(); - - return mat; -} - -/* -QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) -{ - QImage qImage(data, width, height, format); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); -} - -QString ImageUtil::QImageToBase64(QImage image) -{ - QByteArray ba; - QBuffer buf(&ba); - image.save(&buf, "bmp"); - QString base64String = ba.toBase64(); - return base64String; -} - -cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) -{ - cv::Mat matClone = src.clone(); - cv::Rect bigRect; - - bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; - bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; - bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; - bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; - - cv::Mat roi = matClone(bigRect); - - return roi; -} -*/ +#include "ImageUtil.h" + +ImageUtil::ImageUtil() +{ + +} + +QImage ImageUtil::MatImageToQImage(const cv::Mat &src) +{ + //CV_8UC1 8位无符号的单通道---灰度图片 + if(src.type() == CV_8UC1) + { + QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); + return qImage; + } + //为3通道的彩色图片 + else if(src.type() == CV_8UC3) + { + //得到图像的的首地址 + const uchar *pSrc = (const uchar*)src.data; + //以src构造图片 + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); + } + //四通道图片, 带Alpha通道的RGB彩色图像 + else if(src.type() == CV_8UC4) + { + const uchar *pSrc = (const uchar*)src.data; + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); + //返回图像的子区域作为一个新图像 + return qImage.copy(); + } + else + { + return QImage(); + } +} + +cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) +{ + cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); + return img; +} + +cv::Mat ImageUtil::QImageToMat(QImage image) +{ + cv::Mat mat; + switch(image.format()) + { + case QImage::Format_ARGB32: + case QImage::Format_RGB32: + case QImage::Format_ARGB32_Premultiplied: + mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_RGB888: + mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); + cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); + break; + case QImage::Format_Indexed8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_Grayscale8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); + break; + + default: + break; + } + + mat = mat.clone(); + + return mat; +} + +/* +QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) +{ + QImage qImage(data, width, height, format); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); +} + +QString ImageUtil::QImageToBase64(QImage image) +{ + QByteArray ba; + QBuffer buf(&ba); + image.save(&buf, "bmp"); + QString base64String = ba.toBase64(); + return base64String; +} + +cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) +{ + cv::Mat matClone = src.clone(); + cv::Rect bigRect; + + bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; + bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; + bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; + bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; + + cv::Mat roi = matClone(bigRect); + + return roi; +} +*/ diff --git a/utils/ImageUtil.h b/utils/ImageUtil.h index d9bf00a..4b702f4 100644 --- a/utils/ImageUtil.h +++ b/utils/ImageUtil.h @@ -1,23 +1,23 @@ -#ifndef IMAGEUTIL_H -#define IMAGEUTIL_H - -#include -#include -#include "opencv2/opencv.hpp" - -class ImageUtil -{ -public: - ImageUtil(); - - static QImage MatImageToQImage(const cv::Mat &src); -// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); - - static cv::Mat ucharToMat(unsigned char * data, int row, int col); - static cv::Mat QImageToMat(QImage image); -// static QString QImageToBase64(QImage image); - -// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); -}; - -#endif // IMAGEUTIL_H +#ifndef IMAGEUTIL_H +#define IMAGEUTIL_H + +#include +#include +#include "opencv2/opencv.hpp" + +class ImageUtil +{ +public: + ImageUtil(); + + static QImage MatImageToQImage(const cv::Mat &src); +// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); + + static cv::Mat ucharToMat(unsigned char * data, int row, int col); + static cv::Mat QImageToMat(QImage image); +// static QString QImageToBase64(QImage image); + +// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); +}; + +#endif // IMAGEUTIL_H diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp index 663db0f..05c4c68 100644 --- a/utils/SettingConfig.cpp +++ b/utils/SettingConfig.cpp @@ -1,4 +1,4 @@ -#include "SettingConfig.h" +#include "SettingConfig.h" #include SettingConfig::SettingConfig() @@ -34,6 +34,9 @@ LOG_FILE = getProperty("log", "logFile").toString(); LOG_LEVEL = getProperty("log", "logLevel").toString(); + + DEBUG_CAMERA_ROTATE = getProperty("debug", "cameraRotate").toString(); + DEBUG_SEGMENT_IP = getProperty("debug", "segmentIp").toString(); } diff --git a/utils/SettingConfig.h b/utils/SettingConfig.h index b65f553..c35d6ab 100644 --- a/utils/SettingConfig.h +++ b/utils/SettingConfig.h @@ -1,4 +1,4 @@ -#ifndef SETTINGCONFIG_H +#ifndef SETTINGCONFIG_H #define SETTINGCONFIG_H #include @@ -55,6 +55,9 @@ QString LOG_FILE; QString LOG_LEVEL; + QString DEBUG_CAMERA_ROTATE; + QString DEBUG_SEGMENT_IP; + private: SettingConfig(); diff --git a/utils/SocketClientUtil.cpp b/utils/SocketClientUtil.cpp index d539d64..20b8869 100644 --- a/utils/SocketClientUtil.cpp +++ b/utils/SocketClientUtil.cpp @@ -1,9 +1,10 @@ -#include "SocketClientUtil.h" +#include "SocketClientUtil.h" #include "utils/ByteUtil.h" SocketClientUtil::SocketClientUtil(QObject *parent) : QObject(parent) { QObject::connect(&objClient, &QTcpSocket::readyRead, this, &SocketClientUtil::readData); + QObject::connect(&objClient, &QTcpSocket::disconnected, this, &SocketClientUtil::socketReconnect); } void SocketClientUtil::connect(QString host, int port) @@ -16,6 +17,10 @@ void SocketClientUtil::closeConnect() { + QObject::disconnect(&objClient, &QTcpSocket::readyRead, this, &SocketClientUtil::readData); + QObject::disconnect(&objClient, &QTcpSocket::disconnected, this, &SocketClientUtil::socketReconnect); + + objClient.disconnectFromHost(); objClient.close(); } @@ -45,3 +50,9 @@ emit this->responseReaded(); } } + +void SocketClientUtil::socketReconnect() +{ + objClient.close(); + objClient.connectToHost(this->host, this->port); +} diff --git a/utils/SocketClientUtil.h b/utils/SocketClientUtil.h index 96b60e0..8bd1b8c 100644 --- a/utils/SocketClientUtil.h +++ b/utils/SocketClientUtil.h @@ -1,4 +1,4 @@ -#ifndef SOCKETCLIENTUTIL_H +#ifndef SOCKETCLIENTUTIL_H #define SOCKETCLIENTUTIL_H #include @@ -30,6 +30,7 @@ public slots: void readData(); void sendData(QByteArray data); + void socketReconnect(); }; diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/device/IrisCameraCapEventHandler.h b/device/IrisCameraCapEventHandler.h index 8b976c5..94f5594 100644 --- a/device/IrisCameraCapEventHandler.h +++ b/device/IrisCameraCapEventHandler.h @@ -1,10 +1,9 @@ -#ifndef IRISCAMERACAPEVENTHANDLER_H +#ifndef IRISCAMERACAPEVENTHANDLER_H #define IRISCAMERACAPEVENTHANDLER_H #include #include -#include "include/opencv2/opencv.hpp" -#include "include/daheng/GalaxyIncludes.h" +#include #include "casic/iris/CasicIrisInterface.h" #include "ProMemory.h" diff --git a/device/IrisCameraController.cpp b/device/IrisCameraController.cpp index 0928176..4eea013 100644 --- a/device/IrisCameraController.cpp +++ b/device/IrisCameraController.cpp @@ -1,8 +1,8 @@ -#include "IrisCameraController.h" +#include "IrisCameraController.h" IrisCameraController::IrisCameraController(QObject *parent) : QObject(parent) { - this->irisCamHandler = new IrisCameraCapEventHandler(this); + initIrisCameraController(); } IrisCameraController::~IrisCameraController() { @@ -10,101 +10,204 @@ } -void IrisCameraController::initIrisCamera() +void IrisCameraController::initIrisCameraController() { - IGXFactory::GetInstance().Init(); + // Init GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXInitLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraInitError(); + LOG_ERROR("[CameraController]初始化虹膜相机失败"); + return ; + } + LOG_INFO("[CameraController]初始化虹膜相机成功"); //枚举设备 - IGXFactory::GetInstance().UpdateDeviceList(1000, irisCamList); - - this->OpenDevice(); + UpdateDeviceList(); } void IrisCameraController::openIrisCamera() { - //设置Buffer处理模式 - irisStreamFeaturePtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst"); + GX_STATUS emStatus = GX_STATUS_SUCCESS; - //注册回调函数 - irisStreamPtr->RegisterCaptureCallback(irisCamHandler, &irisCamPtr); + if (m_ui32DeviceNum > 0) { + emStatus = GXOpenDeviceByIndex(1, &m_hDevice); - //开启流层通道 - irisStreamPtr->StartGrab(); + if (emStatus == GX_STATUS_SUCCESS) { + LOG_INFO("[CameraController]开启虹膜相机成功"); - //发送开采命令 - irisFeaturePtr->GetCommandFeature("AcquisitionStart")->Execute(); + // isOpen flag set true + m_bOpen = true; - // 启动定时器 - TimeCounterUtil::getInstance().irisCapCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); // 50ms执行一次定时器 + SetUpAcquisitionThread(); + } + } + + return; } void IrisCameraController::closeIrisCamera() { - + // Release GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXCloseLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraTermError(); + } } void IrisCameraController::startCapture() { // 获取定时器, 绑定定时函数 - connect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString()); + bool bSetDone = false; + // Set acquisition buffer number + bSetDone = SetAcquisitionBufferNum(); + if (!bSetDone) + { + return; + } + + bool bPrepareDone = false; + // Alloc resource for image acquisition + bPrepareDone = m_pobjAcqThread->PrepareForShowImg(); + if (!bPrepareDone) + { + return; + } + + // Device start acquisition and start acquisition thread + StartAcquisition(); + + LOG_DEBUG(QString("[CameraController][startCapture]虹膜相机拍图").toStdString()); + + // Do not start timer when acquisition start failed + if (!m_bAcquisitionStart) + { + return; + } } void IrisCameraController::stopCapture() { - // 获取定时器, 绑定定时函数 - disconnect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString()); - + this->StopAcquisition(); } -void IrisCameraController::getOneFaceFrm() +void IrisCameraController::SetUpAcquisitionThread() { - // 发送软触发命令(在触发模式开启时有效) - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::getLeftAndRightEyeFrame() -{ - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::OpenDevice() -{ - auto device = irisCamList.at(0); - - irisCamPtr = IGXFactory::GetInstance().OpenDeviceByUserID(device.GetUserID(), GX_ACCESS_EXCLUSIVE); - irisFeaturePtr = irisCamPtr->GetRemoteFeatureControl(); - - // 判断设备流是否大于零, 如果大于零则打开流 - int nStreamCount = irisCamPtr->GetStreamCount(); - if (nStreamCount > 0) + // if Acquisition thread is on Stop acquisition thread + if (m_pobjAcqThread != NULL) { - irisStreamPtr = irisCamPtr->OpenStream(0); - irisStreamFeaturePtr = irisStreamPtr->GetFeatureControl(); + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Release acquisition thread object + RELEASE_ALLOC_MEM(m_pobjAcqThread); } - // 建议用户在打开网络相机之后, 根据当前网络环境设置相机的流通道包长值, - // 以提高网络相机的采集性能, 设置方法参考以下代码。 - GX_DEVICE_CLASS_LIST objDeviceClass = irisCamPtr->GetDeviceInfo().GetDeviceClass(); - if(GX_DEVICE_CLASS_GEV == objDeviceClass) + // Instantiation acquisition thread + try { - // 判断设备是否支持流通道数据包功能 - if(true == irisFeaturePtr->IsImplemented("GevSCPSPacketSize")) - { - // 获取当前网络环境的最优包长值 - int nPacketSize = irisStreamPtr->GetOptimalPacketSize(); - // 将最优包长值设置为当前设备的流通道包长值 - irisFeaturePtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize); - } + m_pobjAcqThread = new CAcquisitionThread(); + m_pobjAcqThread->m_hDevice = m_hDevice; + } + catch (std::bad_alloc &e) + { + QMessageBox::about(NULL, "Allocate memory error", "Cannot allocate memory, please exit this app!"); + RELEASE_ALLOC_MEM(m_pobjAcqThread); + return; } - //设置采集模式为连续采集模式 - irisFeaturePtr->GetEnumFeature("AcquisitionMode")->SetValue("Continuous"); + return; +} - //设置触发模式关 - irisFeaturePtr->GetEnumFeature("TriggerMode")->SetValue("On"); - irisFeaturePtr->GetEnumFeature("TriggerSource")->SetValue("Software"); +void IrisCameraController::UpdateDeviceList() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Enumerate Devcie List + emStatus = GXUpdateDeviceList(&m_ui32DeviceNum, ENUMRATE_TIME_OUT); + + LOG_INFO(QString("[CameraController]枚举虹膜相机成功[%1]").arg(m_ui32DeviceNum).toStdString()); + + return; +} + +void IrisCameraController::StartAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + emStatus = GXStreamOn(m_hDevice); + + // Set acquisition thread run flag + m_pobjAcqThread->m_bAcquisitionThreadFlag = true; + + // Acquisition thread start + m_pobjAcqThread->start(); + + // isStart flag set true + m_bAcquisitionStart = true; + + return; +} + +void IrisCameraController::StopAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Turn off stream + emStatus = GXStreamOff(m_hDevice); + + // isStart flag set false + m_bAcquisitionStart = false; + + return; +} + +bool IrisCameraController::SetAcquisitionBufferNum() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + uint64_t ui64BufferNum = 0; + int64_t i64PayloadSize = 0; + + // Get device current payload size + emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &i64PayloadSize); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Set buffer quantity of acquisition queue + if (i64PayloadSize == 0) + { + return false; + } + + // Calculate a reasonable number of Buffers for different payload size + // Small ROI and high frame rate will requires more acquisition Buffer + const size_t MAX_MEMORY_SIZE = 8 * 1024 * 1024; // The maximum number of memory bytes available for allocating frame Buffer + const size_t MIN_BUFFER_NUM = 5; // Minimum frame Buffer number + const size_t MAX_BUFFER_NUM = 450; // Maximum frame Buffer number + ui64BufferNum = MAX_MEMORY_SIZE / i64PayloadSize; + ui64BufferNum = (ui64BufferNum <= MIN_BUFFER_NUM) ? MIN_BUFFER_NUM : ui64BufferNum; + ui64BufferNum = (ui64BufferNum >= MAX_BUFFER_NUM) ? MAX_BUFFER_NUM : ui64BufferNum; + + emStatus = GXSetAcqusitionBufferNumber(m_hDevice, ui64BufferNum); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Transfer buffer number to acquisition thread class for using GXDQAllBufs + m_pobjAcqThread->m_ui64AcquisitionBufferNum = ui64BufferNum; + + return true; } diff --git a/device/IrisCameraController.h b/device/IrisCameraController.h index 5d7e269..67cbe2f 100644 --- a/device/IrisCameraController.h +++ b/device/IrisCameraController.h @@ -1,11 +1,12 @@ -#ifndef IRISCAMERACONTROLLER_H +#ifndef IRISCAMERACONTROLLER_H #define IRISCAMERACONTROLLER_H #include -#include "IrisCameraCapEventHandler.h" +#include "AcquisitionThread.h" +#include "utils/UtilInclude.h" -class IrisCameraCapEventHandler; +#define ENUMRATE_TIME_OUT 200 class IrisCameraController : public QObject { @@ -14,36 +15,31 @@ explicit IrisCameraController(QObject *parent = nullptr); ~IrisCameraController(); - // 初始化并打开人脸相机 - void initIrisCamera(); void openIrisCamera(); void closeIrisCamera(); void startCapture(); void stopCapture(); - void getLeftAndRightEyeFrame(); + CAcquisitionThread * m_pobjAcqThread; + GX_DEV_HANDLE m_hDevice; ///< Device Handle + uint32_t m_ui32DeviceNum; ///< Device number enumerated - IrisCameraCapEventHandler * irisCamHandler; + bool m_bOpen; ///< Flag : camera is opened or not + bool m_bAcquisitionStart; ///< Flag : camera is acquiring or not private: - GxIAPICPP::gxdeviceinfo_vector irisCamList; - - CGXDevicePointer irisCamPtr; ///< 设备句柄 - - CGXStreamPointer irisStreamPtr; ///< 左眼设备流 - - CGXFeatureControlPointer irisFeaturePtr; ///< 左眼属性控制器 - - CGXFeatureControlPointer irisStreamFeaturePtr; ///< 左眼流层控制器对象 - - void OpenDevice(); + // 初始化并打开人脸相机 + void initIrisCameraController(); + void SetUpAcquisitionThread(); + void UpdateDeviceList(); + bool SetAcquisitionBufferNum(); + void StartAcquisition(); + void StopAcquisition(); signals: - -public slots: - void getOneFaceFrm(); - + void irisCameraInitError(); + void irisCameraTermError(); }; #endif // IRISCAMERACONTROLLER_H diff --git a/device/device.pri b/device/device.pri index d1330a0..583721b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,13 +1,14 @@ HEADERS += $$PWD/IrisCameraController.h -HEADERS += $$PWD/IrisCameraCapEventHandler.h -#HEADERS += $$PWD/iris/IrisRegistProcess.h +#HEADERS += $$PWD/IrisCameraCapEventHandler.h +HEADERS += $$PWD/Common.h +HEADERS += $$PWD/AcquisitionThread.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h SOURCES += $$PWD/IrisCameraController.cpp -SOURCES += $$PWD/IrisCameraCapEventHandler.cpp -#SOURCES += $$PWD/iris/IrisRegistProcess.cpp +#SOURCES += $$PWD/IrisCameraCapEventHandler.cpp +SOURCES += $$PWD/AcquisitionThread.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 38f54fe..e4c8a02 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -11,7 +11,7 @@ // 连接算法服务 clientUtil = new SocketClientUtil(this); - clientUtil->connect("192.168.83.223", 50007); + clientUtil->connect(SettingConfig::getInstance().DEBUG_SEGMENT_IP, 50007); // 调用socket发送消息 connect(this, &IrisRecogProcess::sendDataToExract, clientUtil, &SocketClientUtil::sendData); @@ -43,18 +43,18 @@ continue; } - // 1. 图像栈中没有图像则直接返回 - if (ProMemory::getInstance().isIrisQueueEmpty() == true) + // 1. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 + if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) { - qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); + qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } - // 2. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 - if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) + // 2. 图像栈中没有图像则直接返回 + if (ProMemory::getInstance().isIrisQueueEmpty() == true) { - qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); + qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } @@ -73,7 +73,7 @@ int findEyeLast = timer.elapsed(); qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); -// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.matData = cv::imread("/home/casic/code/irisLogs/145333.552.bmp", 0); // irisInfo.hasEye = true; // 4.1 没有找到眼睛则返回 @@ -117,11 +117,10 @@ // 缩放到320 * 240 cv::resize(segMat, segMat, cv::Size(SettingConfig::getInstance().IRIS_WIDTH * 0.5, SettingConfig::getInstance().IRIS_HEIGHT * 0.5)); - - // std::string filename = QString("%1\\%2\\%3-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - // cv::imwrite(filename, segMat); - // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - +/* + std::string filename = QString("%1/%2/%3-seg.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(filename, segMat); +*/ int segMatSize = segMat.cols * segMat.rows; QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 @@ -167,9 +166,9 @@ // 成功接收后清除缓存区 clientUtil->resetRecvBuffer(); /* - std::string pupilSeg = QString("%1\\%2\\%3-pupil-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string maskSeg = QString("%1\\%2\\%3-mask-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string irisSeg = QString("%1\\%2\\%3-iris-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string pupilSeg = QString("%1/%2/%3-pupil-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); cv::imwrite(pupilSeg, pupil); cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); @@ -196,12 +195,20 @@ CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; irisInfo = casic::iris::CasicIrisInterface::getInstance().irisEncode(irisInfo); /* - std::string codeFilename = QString("%1\\%2\\%3-code.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string codeFilename = QString("%1/%2/%3-code.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string maskFilename = QString("%1/%2/%3-mask.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); */ + if (irisInfo.postProcSucc == false) { + qDebug() << "算法post process失败,暂停200ms"; + + addOneTryCount(); + this->msleep(THREAD_MSLEEP); // 200ms后再判断 + continue; + } + // 从编码中提取特征值 irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); @@ -211,6 +218,8 @@ CasicIrisRecState::getInstance().extractTmLast = encodeLast; CasicIrisRecState::getInstance().recogTimeLast += encodeLast; +// cv::imwrite(QString("%1/%2/%3.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(), irisInfo.matData); + // 开始匹配 timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) @@ -219,7 +228,7 @@ float score = casic::iris::CasicIrisInterface::getInstance().calculatePairPoints(feature.irisFeatureCode, irisInfo.irisFeatureCode); // 计算压缩编码的比较值 -// cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); +// cv::imwrite(QString("%1/%2/%3-%4.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; @@ -251,7 +260,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } @@ -268,7 +277,7 @@ CasicIrisRecState::getInstance().tryCount = 0; this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); emit failedMatchedIris(); @@ -290,7 +299,7 @@ // 识别失败时暂停工作 待返回识别界面时再开始工作和拍图 this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); } } else if (ProMemory::getInstance().appState == AppConstants::ApplicationState::STATE_WORKING) @@ -298,7 +307,8 @@ CasicIrisRecState::getInstance().noEyeCount++; // 如果在工作状态 则超过一定次数后返回待机 - if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT) + if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT && + SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT > 0) { // 发送信号待机 emit backToLockScreen(); diff --git a/device/iris/IrisRecogProcess.h b/device/iris/IrisRecogProcess.h index 9a3eec6..e21c1a7 100644 --- a/device/iris/IrisRecogProcess.h +++ b/device/iris/IrisRecogProcess.h @@ -1,4 +1,4 @@ -#ifndef IRISRECOGPROCESS_H +#ifndef IRISRECOGPROCESS_H #define IRISRECOGPROCESS_H #define THREAD_MSLEEP 200 @@ -10,6 +10,7 @@ #include "ProMemory.h" #include "device/iris/CasicIrisRecState.h" +#include "casic/iris/CasicIrisInterface.h" class IrisRecogProcess : public QThread { diff --git a/main.cpp b/main.cpp index 9052ddb..3bfb1c6 100644 --- a/main.cpp +++ b/main.cpp @@ -1,11 +1,11 @@ -#include "MainWindowForm.h" - -#include - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - MainWindowForm w; - w.show(); - return a.exec(); -} +#include "MainWindowForm.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindowForm w; + w.show(); + return a.exec(); +} diff --git a/utils/ImageUtil.cpp b/utils/ImageUtil.cpp index ff77331..d40ea79 100644 --- a/utils/ImageUtil.cpp +++ b/utils/ImageUtil.cpp @@ -1,107 +1,107 @@ -#include "ImageUtil.h" - -ImageUtil::ImageUtil() -{ - -} - -QImage ImageUtil::MatImageToQImage(const cv::Mat &src) -{ - //CV_8UC1 8位无符号的单通道---灰度图片 - if(src.type() == CV_8UC1) - { - QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); - return qImage; - } - //为3通道的彩色图片 - else if(src.type() == CV_8UC3) - { - //得到图像的的首地址 - const uchar *pSrc = (const uchar*)src.data; - //以src构造图片 - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); - } - //四通道图片, 带Alpha通道的RGB彩色图像 - else if(src.type() == CV_8UC4) - { - const uchar *pSrc = (const uchar*)src.data; - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); - //返回图像的子区域作为一个新图像 - return qImage.copy(); - } - else - { - return QImage(); - } -} - -cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) -{ - cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); - return img; -} - -cv::Mat ImageUtil::QImageToMat(QImage image) -{ - cv::Mat mat; - switch(image.format()) - { - case QImage::Format_ARGB32: - case QImage::Format_RGB32: - case QImage::Format_ARGB32_Premultiplied: - mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_RGB888: - mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); - cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); - break; - case QImage::Format_Indexed8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_Grayscale8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); - break; - - default: - break; - } - - mat = mat.clone(); - - return mat; -} - -/* -QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) -{ - QImage qImage(data, width, height, format); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); -} - -QString ImageUtil::QImageToBase64(QImage image) -{ - QByteArray ba; - QBuffer buf(&ba); - image.save(&buf, "bmp"); - QString base64String = ba.toBase64(); - return base64String; -} - -cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) -{ - cv::Mat matClone = src.clone(); - cv::Rect bigRect; - - bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; - bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; - bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; - bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; - - cv::Mat roi = matClone(bigRect); - - return roi; -} -*/ +#include "ImageUtil.h" + +ImageUtil::ImageUtil() +{ + +} + +QImage ImageUtil::MatImageToQImage(const cv::Mat &src) +{ + //CV_8UC1 8位无符号的单通道---灰度图片 + if(src.type() == CV_8UC1) + { + QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); + return qImage; + } + //为3通道的彩色图片 + else if(src.type() == CV_8UC3) + { + //得到图像的的首地址 + const uchar *pSrc = (const uchar*)src.data; + //以src构造图片 + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); + } + //四通道图片, 带Alpha通道的RGB彩色图像 + else if(src.type() == CV_8UC4) + { + const uchar *pSrc = (const uchar*)src.data; + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); + //返回图像的子区域作为一个新图像 + return qImage.copy(); + } + else + { + return QImage(); + } +} + +cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) +{ + cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); + return img; +} + +cv::Mat ImageUtil::QImageToMat(QImage image) +{ + cv::Mat mat; + switch(image.format()) + { + case QImage::Format_ARGB32: + case QImage::Format_RGB32: + case QImage::Format_ARGB32_Premultiplied: + mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_RGB888: + mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); + cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); + break; + case QImage::Format_Indexed8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_Grayscale8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); + break; + + default: + break; + } + + mat = mat.clone(); + + return mat; +} + +/* +QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) +{ + QImage qImage(data, width, height, format); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); +} + +QString ImageUtil::QImageToBase64(QImage image) +{ + QByteArray ba; + QBuffer buf(&ba); + image.save(&buf, "bmp"); + QString base64String = ba.toBase64(); + return base64String; +} + +cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) +{ + cv::Mat matClone = src.clone(); + cv::Rect bigRect; + + bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; + bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; + bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; + bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; + + cv::Mat roi = matClone(bigRect); + + return roi; +} +*/ diff --git a/utils/ImageUtil.h b/utils/ImageUtil.h index d9bf00a..4b702f4 100644 --- a/utils/ImageUtil.h +++ b/utils/ImageUtil.h @@ -1,23 +1,23 @@ -#ifndef IMAGEUTIL_H -#define IMAGEUTIL_H - -#include -#include -#include "opencv2/opencv.hpp" - -class ImageUtil -{ -public: - ImageUtil(); - - static QImage MatImageToQImage(const cv::Mat &src); -// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); - - static cv::Mat ucharToMat(unsigned char * data, int row, int col); - static cv::Mat QImageToMat(QImage image); -// static QString QImageToBase64(QImage image); - -// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); -}; - -#endif // IMAGEUTIL_H +#ifndef IMAGEUTIL_H +#define IMAGEUTIL_H + +#include +#include +#include "opencv2/opencv.hpp" + +class ImageUtil +{ +public: + ImageUtil(); + + static QImage MatImageToQImage(const cv::Mat &src); +// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); + + static cv::Mat ucharToMat(unsigned char * data, int row, int col); + static cv::Mat QImageToMat(QImage image); +// static QString QImageToBase64(QImage image); + +// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); +}; + +#endif // IMAGEUTIL_H diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp index 663db0f..05c4c68 100644 --- a/utils/SettingConfig.cpp +++ b/utils/SettingConfig.cpp @@ -1,4 +1,4 @@ -#include "SettingConfig.h" +#include "SettingConfig.h" #include SettingConfig::SettingConfig() @@ -34,6 +34,9 @@ LOG_FILE = getProperty("log", "logFile").toString(); LOG_LEVEL = getProperty("log", "logLevel").toString(); + + DEBUG_CAMERA_ROTATE = getProperty("debug", "cameraRotate").toString(); + DEBUG_SEGMENT_IP = getProperty("debug", "segmentIp").toString(); } diff --git a/utils/SettingConfig.h b/utils/SettingConfig.h index b65f553..c35d6ab 100644 --- a/utils/SettingConfig.h +++ b/utils/SettingConfig.h @@ -1,4 +1,4 @@ -#ifndef SETTINGCONFIG_H +#ifndef SETTINGCONFIG_H #define SETTINGCONFIG_H #include @@ -55,6 +55,9 @@ QString LOG_FILE; QString LOG_LEVEL; + QString DEBUG_CAMERA_ROTATE; + QString DEBUG_SEGMENT_IP; + private: SettingConfig(); diff --git a/utils/SocketClientUtil.cpp b/utils/SocketClientUtil.cpp index d539d64..20b8869 100644 --- a/utils/SocketClientUtil.cpp +++ b/utils/SocketClientUtil.cpp @@ -1,9 +1,10 @@ -#include "SocketClientUtil.h" +#include "SocketClientUtil.h" #include "utils/ByteUtil.h" SocketClientUtil::SocketClientUtil(QObject *parent) : QObject(parent) { QObject::connect(&objClient, &QTcpSocket::readyRead, this, &SocketClientUtil::readData); + QObject::connect(&objClient, &QTcpSocket::disconnected, this, &SocketClientUtil::socketReconnect); } void SocketClientUtil::connect(QString host, int port) @@ -16,6 +17,10 @@ void SocketClientUtil::closeConnect() { + QObject::disconnect(&objClient, &QTcpSocket::readyRead, this, &SocketClientUtil::readData); + QObject::disconnect(&objClient, &QTcpSocket::disconnected, this, &SocketClientUtil::socketReconnect); + + objClient.disconnectFromHost(); objClient.close(); } @@ -45,3 +50,9 @@ emit this->responseReaded(); } } + +void SocketClientUtil::socketReconnect() +{ + objClient.close(); + objClient.connectToHost(this->host, this->port); +} diff --git a/utils/SocketClientUtil.h b/utils/SocketClientUtil.h index 96b60e0..8bd1b8c 100644 --- a/utils/SocketClientUtil.h +++ b/utils/SocketClientUtil.h @@ -1,4 +1,4 @@ -#ifndef SOCKETCLIENTUTIL_H +#ifndef SOCKETCLIENTUTIL_H #define SOCKETCLIENTUTIL_H #include @@ -30,6 +30,7 @@ public slots: void readData(); void sendData(QByteArray data); + void socketReconnect(); }; diff --git a/utils/TimeCounterUtil.cpp b/utils/TimeCounterUtil.cpp index 275945f..78c3d69 100644 --- a/utils/TimeCounterUtil.cpp +++ b/utils/TimeCounterUtil.cpp @@ -1,8 +1,9 @@ -#include "TimeCounterUtil.h" - -TimeCounterUtil::TimeCounterUtil() -{ - faceCapCounter = new QTimer(); - irisCapCounter = new QTimer(); - clockCounter = new QTimer(); -} +#include "TimeCounterUtil.h" + +TimeCounterUtil::TimeCounterUtil() +{ + faceCapCounter = new QTimer(); + irisCapCounter = new QTimer(); + clockCounter = new QTimer(); + videoCounter = new QTimer(); +} diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/device/IrisCameraCapEventHandler.h b/device/IrisCameraCapEventHandler.h index 8b976c5..94f5594 100644 --- a/device/IrisCameraCapEventHandler.h +++ b/device/IrisCameraCapEventHandler.h @@ -1,10 +1,9 @@ -#ifndef IRISCAMERACAPEVENTHANDLER_H +#ifndef IRISCAMERACAPEVENTHANDLER_H #define IRISCAMERACAPEVENTHANDLER_H #include #include -#include "include/opencv2/opencv.hpp" -#include "include/daheng/GalaxyIncludes.h" +#include #include "casic/iris/CasicIrisInterface.h" #include "ProMemory.h" diff --git a/device/IrisCameraController.cpp b/device/IrisCameraController.cpp index 0928176..4eea013 100644 --- a/device/IrisCameraController.cpp +++ b/device/IrisCameraController.cpp @@ -1,8 +1,8 @@ -#include "IrisCameraController.h" +#include "IrisCameraController.h" IrisCameraController::IrisCameraController(QObject *parent) : QObject(parent) { - this->irisCamHandler = new IrisCameraCapEventHandler(this); + initIrisCameraController(); } IrisCameraController::~IrisCameraController() { @@ -10,101 +10,204 @@ } -void IrisCameraController::initIrisCamera() +void IrisCameraController::initIrisCameraController() { - IGXFactory::GetInstance().Init(); + // Init GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXInitLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraInitError(); + LOG_ERROR("[CameraController]初始化虹膜相机失败"); + return ; + } + LOG_INFO("[CameraController]初始化虹膜相机成功"); //枚举设备 - IGXFactory::GetInstance().UpdateDeviceList(1000, irisCamList); - - this->OpenDevice(); + UpdateDeviceList(); } void IrisCameraController::openIrisCamera() { - //设置Buffer处理模式 - irisStreamFeaturePtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst"); + GX_STATUS emStatus = GX_STATUS_SUCCESS; - //注册回调函数 - irisStreamPtr->RegisterCaptureCallback(irisCamHandler, &irisCamPtr); + if (m_ui32DeviceNum > 0) { + emStatus = GXOpenDeviceByIndex(1, &m_hDevice); - //开启流层通道 - irisStreamPtr->StartGrab(); + if (emStatus == GX_STATUS_SUCCESS) { + LOG_INFO("[CameraController]开启虹膜相机成功"); - //发送开采命令 - irisFeaturePtr->GetCommandFeature("AcquisitionStart")->Execute(); + // isOpen flag set true + m_bOpen = true; - // 启动定时器 - TimeCounterUtil::getInstance().irisCapCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); // 50ms执行一次定时器 + SetUpAcquisitionThread(); + } + } + + return; } void IrisCameraController::closeIrisCamera() { - + // Release GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXCloseLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraTermError(); + } } void IrisCameraController::startCapture() { // 获取定时器, 绑定定时函数 - connect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString()); + bool bSetDone = false; + // Set acquisition buffer number + bSetDone = SetAcquisitionBufferNum(); + if (!bSetDone) + { + return; + } + + bool bPrepareDone = false; + // Alloc resource for image acquisition + bPrepareDone = m_pobjAcqThread->PrepareForShowImg(); + if (!bPrepareDone) + { + return; + } + + // Device start acquisition and start acquisition thread + StartAcquisition(); + + LOG_DEBUG(QString("[CameraController][startCapture]虹膜相机拍图").toStdString()); + + // Do not start timer when acquisition start failed + if (!m_bAcquisitionStart) + { + return; + } } void IrisCameraController::stopCapture() { - // 获取定时器, 绑定定时函数 - disconnect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString()); - + this->StopAcquisition(); } -void IrisCameraController::getOneFaceFrm() +void IrisCameraController::SetUpAcquisitionThread() { - // 发送软触发命令(在触发模式开启时有效) - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::getLeftAndRightEyeFrame() -{ - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::OpenDevice() -{ - auto device = irisCamList.at(0); - - irisCamPtr = IGXFactory::GetInstance().OpenDeviceByUserID(device.GetUserID(), GX_ACCESS_EXCLUSIVE); - irisFeaturePtr = irisCamPtr->GetRemoteFeatureControl(); - - // 判断设备流是否大于零, 如果大于零则打开流 - int nStreamCount = irisCamPtr->GetStreamCount(); - if (nStreamCount > 0) + // if Acquisition thread is on Stop acquisition thread + if (m_pobjAcqThread != NULL) { - irisStreamPtr = irisCamPtr->OpenStream(0); - irisStreamFeaturePtr = irisStreamPtr->GetFeatureControl(); + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Release acquisition thread object + RELEASE_ALLOC_MEM(m_pobjAcqThread); } - // 建议用户在打开网络相机之后, 根据当前网络环境设置相机的流通道包长值, - // 以提高网络相机的采集性能, 设置方法参考以下代码。 - GX_DEVICE_CLASS_LIST objDeviceClass = irisCamPtr->GetDeviceInfo().GetDeviceClass(); - if(GX_DEVICE_CLASS_GEV == objDeviceClass) + // Instantiation acquisition thread + try { - // 判断设备是否支持流通道数据包功能 - if(true == irisFeaturePtr->IsImplemented("GevSCPSPacketSize")) - { - // 获取当前网络环境的最优包长值 - int nPacketSize = irisStreamPtr->GetOptimalPacketSize(); - // 将最优包长值设置为当前设备的流通道包长值 - irisFeaturePtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize); - } + m_pobjAcqThread = new CAcquisitionThread(); + m_pobjAcqThread->m_hDevice = m_hDevice; + } + catch (std::bad_alloc &e) + { + QMessageBox::about(NULL, "Allocate memory error", "Cannot allocate memory, please exit this app!"); + RELEASE_ALLOC_MEM(m_pobjAcqThread); + return; } - //设置采集模式为连续采集模式 - irisFeaturePtr->GetEnumFeature("AcquisitionMode")->SetValue("Continuous"); + return; +} - //设置触发模式关 - irisFeaturePtr->GetEnumFeature("TriggerMode")->SetValue("On"); - irisFeaturePtr->GetEnumFeature("TriggerSource")->SetValue("Software"); +void IrisCameraController::UpdateDeviceList() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Enumerate Devcie List + emStatus = GXUpdateDeviceList(&m_ui32DeviceNum, ENUMRATE_TIME_OUT); + + LOG_INFO(QString("[CameraController]枚举虹膜相机成功[%1]").arg(m_ui32DeviceNum).toStdString()); + + return; +} + +void IrisCameraController::StartAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + emStatus = GXStreamOn(m_hDevice); + + // Set acquisition thread run flag + m_pobjAcqThread->m_bAcquisitionThreadFlag = true; + + // Acquisition thread start + m_pobjAcqThread->start(); + + // isStart flag set true + m_bAcquisitionStart = true; + + return; +} + +void IrisCameraController::StopAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Turn off stream + emStatus = GXStreamOff(m_hDevice); + + // isStart flag set false + m_bAcquisitionStart = false; + + return; +} + +bool IrisCameraController::SetAcquisitionBufferNum() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + uint64_t ui64BufferNum = 0; + int64_t i64PayloadSize = 0; + + // Get device current payload size + emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &i64PayloadSize); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Set buffer quantity of acquisition queue + if (i64PayloadSize == 0) + { + return false; + } + + // Calculate a reasonable number of Buffers for different payload size + // Small ROI and high frame rate will requires more acquisition Buffer + const size_t MAX_MEMORY_SIZE = 8 * 1024 * 1024; // The maximum number of memory bytes available for allocating frame Buffer + const size_t MIN_BUFFER_NUM = 5; // Minimum frame Buffer number + const size_t MAX_BUFFER_NUM = 450; // Maximum frame Buffer number + ui64BufferNum = MAX_MEMORY_SIZE / i64PayloadSize; + ui64BufferNum = (ui64BufferNum <= MIN_BUFFER_NUM) ? MIN_BUFFER_NUM : ui64BufferNum; + ui64BufferNum = (ui64BufferNum >= MAX_BUFFER_NUM) ? MAX_BUFFER_NUM : ui64BufferNum; + + emStatus = GXSetAcqusitionBufferNumber(m_hDevice, ui64BufferNum); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Transfer buffer number to acquisition thread class for using GXDQAllBufs + m_pobjAcqThread->m_ui64AcquisitionBufferNum = ui64BufferNum; + + return true; } diff --git a/device/IrisCameraController.h b/device/IrisCameraController.h index 5d7e269..67cbe2f 100644 --- a/device/IrisCameraController.h +++ b/device/IrisCameraController.h @@ -1,11 +1,12 @@ -#ifndef IRISCAMERACONTROLLER_H +#ifndef IRISCAMERACONTROLLER_H #define IRISCAMERACONTROLLER_H #include -#include "IrisCameraCapEventHandler.h" +#include "AcquisitionThread.h" +#include "utils/UtilInclude.h" -class IrisCameraCapEventHandler; +#define ENUMRATE_TIME_OUT 200 class IrisCameraController : public QObject { @@ -14,36 +15,31 @@ explicit IrisCameraController(QObject *parent = nullptr); ~IrisCameraController(); - // 初始化并打开人脸相机 - void initIrisCamera(); void openIrisCamera(); void closeIrisCamera(); void startCapture(); void stopCapture(); - void getLeftAndRightEyeFrame(); + CAcquisitionThread * m_pobjAcqThread; + GX_DEV_HANDLE m_hDevice; ///< Device Handle + uint32_t m_ui32DeviceNum; ///< Device number enumerated - IrisCameraCapEventHandler * irisCamHandler; + bool m_bOpen; ///< Flag : camera is opened or not + bool m_bAcquisitionStart; ///< Flag : camera is acquiring or not private: - GxIAPICPP::gxdeviceinfo_vector irisCamList; - - CGXDevicePointer irisCamPtr; ///< 设备句柄 - - CGXStreamPointer irisStreamPtr; ///< 左眼设备流 - - CGXFeatureControlPointer irisFeaturePtr; ///< 左眼属性控制器 - - CGXFeatureControlPointer irisStreamFeaturePtr; ///< 左眼流层控制器对象 - - void OpenDevice(); + // 初始化并打开人脸相机 + void initIrisCameraController(); + void SetUpAcquisitionThread(); + void UpdateDeviceList(); + bool SetAcquisitionBufferNum(); + void StartAcquisition(); + void StopAcquisition(); signals: - -public slots: - void getOneFaceFrm(); - + void irisCameraInitError(); + void irisCameraTermError(); }; #endif // IRISCAMERACONTROLLER_H diff --git a/device/device.pri b/device/device.pri index d1330a0..583721b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,13 +1,14 @@ HEADERS += $$PWD/IrisCameraController.h -HEADERS += $$PWD/IrisCameraCapEventHandler.h -#HEADERS += $$PWD/iris/IrisRegistProcess.h +#HEADERS += $$PWD/IrisCameraCapEventHandler.h +HEADERS += $$PWD/Common.h +HEADERS += $$PWD/AcquisitionThread.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h SOURCES += $$PWD/IrisCameraController.cpp -SOURCES += $$PWD/IrisCameraCapEventHandler.cpp -#SOURCES += $$PWD/iris/IrisRegistProcess.cpp +#SOURCES += $$PWD/IrisCameraCapEventHandler.cpp +SOURCES += $$PWD/AcquisitionThread.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 38f54fe..e4c8a02 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -11,7 +11,7 @@ // 连接算法服务 clientUtil = new SocketClientUtil(this); - clientUtil->connect("192.168.83.223", 50007); + clientUtil->connect(SettingConfig::getInstance().DEBUG_SEGMENT_IP, 50007); // 调用socket发送消息 connect(this, &IrisRecogProcess::sendDataToExract, clientUtil, &SocketClientUtil::sendData); @@ -43,18 +43,18 @@ continue; } - // 1. 图像栈中没有图像则直接返回 - if (ProMemory::getInstance().isIrisQueueEmpty() == true) + // 1. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 + if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) { - qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); + qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } - // 2. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 - if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) + // 2. 图像栈中没有图像则直接返回 + if (ProMemory::getInstance().isIrisQueueEmpty() == true) { - qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); + qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } @@ -73,7 +73,7 @@ int findEyeLast = timer.elapsed(); qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); -// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.matData = cv::imread("/home/casic/code/irisLogs/145333.552.bmp", 0); // irisInfo.hasEye = true; // 4.1 没有找到眼睛则返回 @@ -117,11 +117,10 @@ // 缩放到320 * 240 cv::resize(segMat, segMat, cv::Size(SettingConfig::getInstance().IRIS_WIDTH * 0.5, SettingConfig::getInstance().IRIS_HEIGHT * 0.5)); - - // std::string filename = QString("%1\\%2\\%3-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - // cv::imwrite(filename, segMat); - // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - +/* + std::string filename = QString("%1/%2/%3-seg.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(filename, segMat); +*/ int segMatSize = segMat.cols * segMat.rows; QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 @@ -167,9 +166,9 @@ // 成功接收后清除缓存区 clientUtil->resetRecvBuffer(); /* - std::string pupilSeg = QString("%1\\%2\\%3-pupil-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string maskSeg = QString("%1\\%2\\%3-mask-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string irisSeg = QString("%1\\%2\\%3-iris-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string pupilSeg = QString("%1/%2/%3-pupil-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); cv::imwrite(pupilSeg, pupil); cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); @@ -196,12 +195,20 @@ CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; irisInfo = casic::iris::CasicIrisInterface::getInstance().irisEncode(irisInfo); /* - std::string codeFilename = QString("%1\\%2\\%3-code.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string codeFilename = QString("%1/%2/%3-code.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string maskFilename = QString("%1/%2/%3-mask.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); */ + if (irisInfo.postProcSucc == false) { + qDebug() << "算法post process失败,暂停200ms"; + + addOneTryCount(); + this->msleep(THREAD_MSLEEP); // 200ms后再判断 + continue; + } + // 从编码中提取特征值 irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); @@ -211,6 +218,8 @@ CasicIrisRecState::getInstance().extractTmLast = encodeLast; CasicIrisRecState::getInstance().recogTimeLast += encodeLast; +// cv::imwrite(QString("%1/%2/%3.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(), irisInfo.matData); + // 开始匹配 timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) @@ -219,7 +228,7 @@ float score = casic::iris::CasicIrisInterface::getInstance().calculatePairPoints(feature.irisFeatureCode, irisInfo.irisFeatureCode); // 计算压缩编码的比较值 -// cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); +// cv::imwrite(QString("%1/%2/%3-%4.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; @@ -251,7 +260,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } @@ -268,7 +277,7 @@ CasicIrisRecState::getInstance().tryCount = 0; this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); emit failedMatchedIris(); @@ -290,7 +299,7 @@ // 识别失败时暂停工作 待返回识别界面时再开始工作和拍图 this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); } } else if (ProMemory::getInstance().appState == AppConstants::ApplicationState::STATE_WORKING) @@ -298,7 +307,8 @@ CasicIrisRecState::getInstance().noEyeCount++; // 如果在工作状态 则超过一定次数后返回待机 - if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT) + if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT && + SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT > 0) { // 发送信号待机 emit backToLockScreen(); diff --git a/device/iris/IrisRecogProcess.h b/device/iris/IrisRecogProcess.h index 9a3eec6..e21c1a7 100644 --- a/device/iris/IrisRecogProcess.h +++ b/device/iris/IrisRecogProcess.h @@ -1,4 +1,4 @@ -#ifndef IRISRECOGPROCESS_H +#ifndef IRISRECOGPROCESS_H #define IRISRECOGPROCESS_H #define THREAD_MSLEEP 200 @@ -10,6 +10,7 @@ #include "ProMemory.h" #include "device/iris/CasicIrisRecState.h" +#include "casic/iris/CasicIrisInterface.h" class IrisRecogProcess : public QThread { diff --git a/main.cpp b/main.cpp index 9052ddb..3bfb1c6 100644 --- a/main.cpp +++ b/main.cpp @@ -1,11 +1,11 @@ -#include "MainWindowForm.h" - -#include - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - MainWindowForm w; - w.show(); - return a.exec(); -} +#include "MainWindowForm.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindowForm w; + w.show(); + return a.exec(); +} diff --git a/utils/ImageUtil.cpp b/utils/ImageUtil.cpp index ff77331..d40ea79 100644 --- a/utils/ImageUtil.cpp +++ b/utils/ImageUtil.cpp @@ -1,107 +1,107 @@ -#include "ImageUtil.h" - -ImageUtil::ImageUtil() -{ - -} - -QImage ImageUtil::MatImageToQImage(const cv::Mat &src) -{ - //CV_8UC1 8位无符号的单通道---灰度图片 - if(src.type() == CV_8UC1) - { - QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); - return qImage; - } - //为3通道的彩色图片 - else if(src.type() == CV_8UC3) - { - //得到图像的的首地址 - const uchar *pSrc = (const uchar*)src.data; - //以src构造图片 - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); - } - //四通道图片, 带Alpha通道的RGB彩色图像 - else if(src.type() == CV_8UC4) - { - const uchar *pSrc = (const uchar*)src.data; - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); - //返回图像的子区域作为一个新图像 - return qImage.copy(); - } - else - { - return QImage(); - } -} - -cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) -{ - cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); - return img; -} - -cv::Mat ImageUtil::QImageToMat(QImage image) -{ - cv::Mat mat; - switch(image.format()) - { - case QImage::Format_ARGB32: - case QImage::Format_RGB32: - case QImage::Format_ARGB32_Premultiplied: - mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_RGB888: - mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); - cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); - break; - case QImage::Format_Indexed8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_Grayscale8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); - break; - - default: - break; - } - - mat = mat.clone(); - - return mat; -} - -/* -QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) -{ - QImage qImage(data, width, height, format); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); -} - -QString ImageUtil::QImageToBase64(QImage image) -{ - QByteArray ba; - QBuffer buf(&ba); - image.save(&buf, "bmp"); - QString base64String = ba.toBase64(); - return base64String; -} - -cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) -{ - cv::Mat matClone = src.clone(); - cv::Rect bigRect; - - bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; - bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; - bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; - bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; - - cv::Mat roi = matClone(bigRect); - - return roi; -} -*/ +#include "ImageUtil.h" + +ImageUtil::ImageUtil() +{ + +} + +QImage ImageUtil::MatImageToQImage(const cv::Mat &src) +{ + //CV_8UC1 8位无符号的单通道---灰度图片 + if(src.type() == CV_8UC1) + { + QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); + return qImage; + } + //为3通道的彩色图片 + else if(src.type() == CV_8UC3) + { + //得到图像的的首地址 + const uchar *pSrc = (const uchar*)src.data; + //以src构造图片 + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); + } + //四通道图片, 带Alpha通道的RGB彩色图像 + else if(src.type() == CV_8UC4) + { + const uchar *pSrc = (const uchar*)src.data; + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); + //返回图像的子区域作为一个新图像 + return qImage.copy(); + } + else + { + return QImage(); + } +} + +cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) +{ + cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); + return img; +} + +cv::Mat ImageUtil::QImageToMat(QImage image) +{ + cv::Mat mat; + switch(image.format()) + { + case QImage::Format_ARGB32: + case QImage::Format_RGB32: + case QImage::Format_ARGB32_Premultiplied: + mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_RGB888: + mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); + cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); + break; + case QImage::Format_Indexed8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_Grayscale8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); + break; + + default: + break; + } + + mat = mat.clone(); + + return mat; +} + +/* +QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) +{ + QImage qImage(data, width, height, format); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); +} + +QString ImageUtil::QImageToBase64(QImage image) +{ + QByteArray ba; + QBuffer buf(&ba); + image.save(&buf, "bmp"); + QString base64String = ba.toBase64(); + return base64String; +} + +cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) +{ + cv::Mat matClone = src.clone(); + cv::Rect bigRect; + + bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; + bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; + bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; + bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; + + cv::Mat roi = matClone(bigRect); + + return roi; +} +*/ diff --git a/utils/ImageUtil.h b/utils/ImageUtil.h index d9bf00a..4b702f4 100644 --- a/utils/ImageUtil.h +++ b/utils/ImageUtil.h @@ -1,23 +1,23 @@ -#ifndef IMAGEUTIL_H -#define IMAGEUTIL_H - -#include -#include -#include "opencv2/opencv.hpp" - -class ImageUtil -{ -public: - ImageUtil(); - - static QImage MatImageToQImage(const cv::Mat &src); -// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); - - static cv::Mat ucharToMat(unsigned char * data, int row, int col); - static cv::Mat QImageToMat(QImage image); -// static QString QImageToBase64(QImage image); - -// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); -}; - -#endif // IMAGEUTIL_H +#ifndef IMAGEUTIL_H +#define IMAGEUTIL_H + +#include +#include +#include "opencv2/opencv.hpp" + +class ImageUtil +{ +public: + ImageUtil(); + + static QImage MatImageToQImage(const cv::Mat &src); +// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); + + static cv::Mat ucharToMat(unsigned char * data, int row, int col); + static cv::Mat QImageToMat(QImage image); +// static QString QImageToBase64(QImage image); + +// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); +}; + +#endif // IMAGEUTIL_H diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp index 663db0f..05c4c68 100644 --- a/utils/SettingConfig.cpp +++ b/utils/SettingConfig.cpp @@ -1,4 +1,4 @@ -#include "SettingConfig.h" +#include "SettingConfig.h" #include SettingConfig::SettingConfig() @@ -34,6 +34,9 @@ LOG_FILE = getProperty("log", "logFile").toString(); LOG_LEVEL = getProperty("log", "logLevel").toString(); + + DEBUG_CAMERA_ROTATE = getProperty("debug", "cameraRotate").toString(); + DEBUG_SEGMENT_IP = getProperty("debug", "segmentIp").toString(); } diff --git a/utils/SettingConfig.h b/utils/SettingConfig.h index b65f553..c35d6ab 100644 --- a/utils/SettingConfig.h +++ b/utils/SettingConfig.h @@ -1,4 +1,4 @@ -#ifndef SETTINGCONFIG_H +#ifndef SETTINGCONFIG_H #define SETTINGCONFIG_H #include @@ -55,6 +55,9 @@ QString LOG_FILE; QString LOG_LEVEL; + QString DEBUG_CAMERA_ROTATE; + QString DEBUG_SEGMENT_IP; + private: SettingConfig(); diff --git a/utils/SocketClientUtil.cpp b/utils/SocketClientUtil.cpp index d539d64..20b8869 100644 --- a/utils/SocketClientUtil.cpp +++ b/utils/SocketClientUtil.cpp @@ -1,9 +1,10 @@ -#include "SocketClientUtil.h" +#include "SocketClientUtil.h" #include "utils/ByteUtil.h" SocketClientUtil::SocketClientUtil(QObject *parent) : QObject(parent) { QObject::connect(&objClient, &QTcpSocket::readyRead, this, &SocketClientUtil::readData); + QObject::connect(&objClient, &QTcpSocket::disconnected, this, &SocketClientUtil::socketReconnect); } void SocketClientUtil::connect(QString host, int port) @@ -16,6 +17,10 @@ void SocketClientUtil::closeConnect() { + QObject::disconnect(&objClient, &QTcpSocket::readyRead, this, &SocketClientUtil::readData); + QObject::disconnect(&objClient, &QTcpSocket::disconnected, this, &SocketClientUtil::socketReconnect); + + objClient.disconnectFromHost(); objClient.close(); } @@ -45,3 +50,9 @@ emit this->responseReaded(); } } + +void SocketClientUtil::socketReconnect() +{ + objClient.close(); + objClient.connectToHost(this->host, this->port); +} diff --git a/utils/SocketClientUtil.h b/utils/SocketClientUtil.h index 96b60e0..8bd1b8c 100644 --- a/utils/SocketClientUtil.h +++ b/utils/SocketClientUtil.h @@ -1,4 +1,4 @@ -#ifndef SOCKETCLIENTUTIL_H +#ifndef SOCKETCLIENTUTIL_H #define SOCKETCLIENTUTIL_H #include @@ -30,6 +30,7 @@ public slots: void readData(); void sendData(QByteArray data); + void socketReconnect(); }; diff --git a/utils/TimeCounterUtil.cpp b/utils/TimeCounterUtil.cpp index 275945f..78c3d69 100644 --- a/utils/TimeCounterUtil.cpp +++ b/utils/TimeCounterUtil.cpp @@ -1,8 +1,9 @@ -#include "TimeCounterUtil.h" - -TimeCounterUtil::TimeCounterUtil() -{ - faceCapCounter = new QTimer(); - irisCapCounter = new QTimer(); - clockCounter = new QTimer(); -} +#include "TimeCounterUtil.h" + +TimeCounterUtil::TimeCounterUtil() +{ + faceCapCounter = new QTimer(); + irisCapCounter = new QTimer(); + clockCounter = new QTimer(); + videoCounter = new QTimer(); +} diff --git a/utils/TimeCounterUtil.h b/utils/TimeCounterUtil.h index 28b29f1..91f8da0 100644 --- a/utils/TimeCounterUtil.h +++ b/utils/TimeCounterUtil.h @@ -1,29 +1,30 @@ -#ifndef TIMECOUNTERUTIL_H -#define TIMECOUNTERUTIL_H - -#include -#include - -class TimeCounterUtil : public QObject -{ -public: - - ~TimeCounterUtil() {}; - TimeCounterUtil(const TimeCounterUtil&)=delete; - TimeCounterUtil& operator=(const TimeCounterUtil&)=delete; - - static TimeCounterUtil& getInstance() { - static TimeCounterUtil instance; - return instance; - } - - QTimer * faceCapCounter; - QTimer * irisCapCounter; - QTimer * clockCounter; - -private: - TimeCounterUtil(); - -}; - -#endif // TIMECOUNTERUTIL_H +#ifndef TIMECOUNTERUTIL_H +#define TIMECOUNTERUTIL_H + +#include +#include + +class TimeCounterUtil : public QObject +{ +public: + + ~TimeCounterUtil() {}; + TimeCounterUtil(const TimeCounterUtil&)=delete; + TimeCounterUtil& operator=(const TimeCounterUtil&)=delete; + + static TimeCounterUtil& getInstance() { + static TimeCounterUtil instance; + return instance; + } + + QTimer * faceCapCounter; + QTimer * irisCapCounter; + QTimer * clockCounter; + QTimer * videoCounter; // show video images on main window + +private: + TimeCounterUtil(); + +}; + +#endif // TIMECOUNTERUTIL_H diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/device/IrisCameraCapEventHandler.h b/device/IrisCameraCapEventHandler.h index 8b976c5..94f5594 100644 --- a/device/IrisCameraCapEventHandler.h +++ b/device/IrisCameraCapEventHandler.h @@ -1,10 +1,9 @@ -#ifndef IRISCAMERACAPEVENTHANDLER_H +#ifndef IRISCAMERACAPEVENTHANDLER_H #define IRISCAMERACAPEVENTHANDLER_H #include #include -#include "include/opencv2/opencv.hpp" -#include "include/daheng/GalaxyIncludes.h" +#include #include "casic/iris/CasicIrisInterface.h" #include "ProMemory.h" diff --git a/device/IrisCameraController.cpp b/device/IrisCameraController.cpp index 0928176..4eea013 100644 --- a/device/IrisCameraController.cpp +++ b/device/IrisCameraController.cpp @@ -1,8 +1,8 @@ -#include "IrisCameraController.h" +#include "IrisCameraController.h" IrisCameraController::IrisCameraController(QObject *parent) : QObject(parent) { - this->irisCamHandler = new IrisCameraCapEventHandler(this); + initIrisCameraController(); } IrisCameraController::~IrisCameraController() { @@ -10,101 +10,204 @@ } -void IrisCameraController::initIrisCamera() +void IrisCameraController::initIrisCameraController() { - IGXFactory::GetInstance().Init(); + // Init GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXInitLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraInitError(); + LOG_ERROR("[CameraController]初始化虹膜相机失败"); + return ; + } + LOG_INFO("[CameraController]初始化虹膜相机成功"); //枚举设备 - IGXFactory::GetInstance().UpdateDeviceList(1000, irisCamList); - - this->OpenDevice(); + UpdateDeviceList(); } void IrisCameraController::openIrisCamera() { - //设置Buffer处理模式 - irisStreamFeaturePtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst"); + GX_STATUS emStatus = GX_STATUS_SUCCESS; - //注册回调函数 - irisStreamPtr->RegisterCaptureCallback(irisCamHandler, &irisCamPtr); + if (m_ui32DeviceNum > 0) { + emStatus = GXOpenDeviceByIndex(1, &m_hDevice); - //开启流层通道 - irisStreamPtr->StartGrab(); + if (emStatus == GX_STATUS_SUCCESS) { + LOG_INFO("[CameraController]开启虹膜相机成功"); - //发送开采命令 - irisFeaturePtr->GetCommandFeature("AcquisitionStart")->Execute(); + // isOpen flag set true + m_bOpen = true; - // 启动定时器 - TimeCounterUtil::getInstance().irisCapCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); // 50ms执行一次定时器 + SetUpAcquisitionThread(); + } + } + + return; } void IrisCameraController::closeIrisCamera() { - + // Release GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXCloseLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraTermError(); + } } void IrisCameraController::startCapture() { // 获取定时器, 绑定定时函数 - connect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString()); + bool bSetDone = false; + // Set acquisition buffer number + bSetDone = SetAcquisitionBufferNum(); + if (!bSetDone) + { + return; + } + + bool bPrepareDone = false; + // Alloc resource for image acquisition + bPrepareDone = m_pobjAcqThread->PrepareForShowImg(); + if (!bPrepareDone) + { + return; + } + + // Device start acquisition and start acquisition thread + StartAcquisition(); + + LOG_DEBUG(QString("[CameraController][startCapture]虹膜相机拍图").toStdString()); + + // Do not start timer when acquisition start failed + if (!m_bAcquisitionStart) + { + return; + } } void IrisCameraController::stopCapture() { - // 获取定时器, 绑定定时函数 - disconnect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString()); - + this->StopAcquisition(); } -void IrisCameraController::getOneFaceFrm() +void IrisCameraController::SetUpAcquisitionThread() { - // 发送软触发命令(在触发模式开启时有效) - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::getLeftAndRightEyeFrame() -{ - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::OpenDevice() -{ - auto device = irisCamList.at(0); - - irisCamPtr = IGXFactory::GetInstance().OpenDeviceByUserID(device.GetUserID(), GX_ACCESS_EXCLUSIVE); - irisFeaturePtr = irisCamPtr->GetRemoteFeatureControl(); - - // 判断设备流是否大于零, 如果大于零则打开流 - int nStreamCount = irisCamPtr->GetStreamCount(); - if (nStreamCount > 0) + // if Acquisition thread is on Stop acquisition thread + if (m_pobjAcqThread != NULL) { - irisStreamPtr = irisCamPtr->OpenStream(0); - irisStreamFeaturePtr = irisStreamPtr->GetFeatureControl(); + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Release acquisition thread object + RELEASE_ALLOC_MEM(m_pobjAcqThread); } - // 建议用户在打开网络相机之后, 根据当前网络环境设置相机的流通道包长值, - // 以提高网络相机的采集性能, 设置方法参考以下代码。 - GX_DEVICE_CLASS_LIST objDeviceClass = irisCamPtr->GetDeviceInfo().GetDeviceClass(); - if(GX_DEVICE_CLASS_GEV == objDeviceClass) + // Instantiation acquisition thread + try { - // 判断设备是否支持流通道数据包功能 - if(true == irisFeaturePtr->IsImplemented("GevSCPSPacketSize")) - { - // 获取当前网络环境的最优包长值 - int nPacketSize = irisStreamPtr->GetOptimalPacketSize(); - // 将最优包长值设置为当前设备的流通道包长值 - irisFeaturePtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize); - } + m_pobjAcqThread = new CAcquisitionThread(); + m_pobjAcqThread->m_hDevice = m_hDevice; + } + catch (std::bad_alloc &e) + { + QMessageBox::about(NULL, "Allocate memory error", "Cannot allocate memory, please exit this app!"); + RELEASE_ALLOC_MEM(m_pobjAcqThread); + return; } - //设置采集模式为连续采集模式 - irisFeaturePtr->GetEnumFeature("AcquisitionMode")->SetValue("Continuous"); + return; +} - //设置触发模式关 - irisFeaturePtr->GetEnumFeature("TriggerMode")->SetValue("On"); - irisFeaturePtr->GetEnumFeature("TriggerSource")->SetValue("Software"); +void IrisCameraController::UpdateDeviceList() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Enumerate Devcie List + emStatus = GXUpdateDeviceList(&m_ui32DeviceNum, ENUMRATE_TIME_OUT); + + LOG_INFO(QString("[CameraController]枚举虹膜相机成功[%1]").arg(m_ui32DeviceNum).toStdString()); + + return; +} + +void IrisCameraController::StartAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + emStatus = GXStreamOn(m_hDevice); + + // Set acquisition thread run flag + m_pobjAcqThread->m_bAcquisitionThreadFlag = true; + + // Acquisition thread start + m_pobjAcqThread->start(); + + // isStart flag set true + m_bAcquisitionStart = true; + + return; +} + +void IrisCameraController::StopAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Turn off stream + emStatus = GXStreamOff(m_hDevice); + + // isStart flag set false + m_bAcquisitionStart = false; + + return; +} + +bool IrisCameraController::SetAcquisitionBufferNum() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + uint64_t ui64BufferNum = 0; + int64_t i64PayloadSize = 0; + + // Get device current payload size + emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &i64PayloadSize); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Set buffer quantity of acquisition queue + if (i64PayloadSize == 0) + { + return false; + } + + // Calculate a reasonable number of Buffers for different payload size + // Small ROI and high frame rate will requires more acquisition Buffer + const size_t MAX_MEMORY_SIZE = 8 * 1024 * 1024; // The maximum number of memory bytes available for allocating frame Buffer + const size_t MIN_BUFFER_NUM = 5; // Minimum frame Buffer number + const size_t MAX_BUFFER_NUM = 450; // Maximum frame Buffer number + ui64BufferNum = MAX_MEMORY_SIZE / i64PayloadSize; + ui64BufferNum = (ui64BufferNum <= MIN_BUFFER_NUM) ? MIN_BUFFER_NUM : ui64BufferNum; + ui64BufferNum = (ui64BufferNum >= MAX_BUFFER_NUM) ? MAX_BUFFER_NUM : ui64BufferNum; + + emStatus = GXSetAcqusitionBufferNumber(m_hDevice, ui64BufferNum); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Transfer buffer number to acquisition thread class for using GXDQAllBufs + m_pobjAcqThread->m_ui64AcquisitionBufferNum = ui64BufferNum; + + return true; } diff --git a/device/IrisCameraController.h b/device/IrisCameraController.h index 5d7e269..67cbe2f 100644 --- a/device/IrisCameraController.h +++ b/device/IrisCameraController.h @@ -1,11 +1,12 @@ -#ifndef IRISCAMERACONTROLLER_H +#ifndef IRISCAMERACONTROLLER_H #define IRISCAMERACONTROLLER_H #include -#include "IrisCameraCapEventHandler.h" +#include "AcquisitionThread.h" +#include "utils/UtilInclude.h" -class IrisCameraCapEventHandler; +#define ENUMRATE_TIME_OUT 200 class IrisCameraController : public QObject { @@ -14,36 +15,31 @@ explicit IrisCameraController(QObject *parent = nullptr); ~IrisCameraController(); - // 初始化并打开人脸相机 - void initIrisCamera(); void openIrisCamera(); void closeIrisCamera(); void startCapture(); void stopCapture(); - void getLeftAndRightEyeFrame(); + CAcquisitionThread * m_pobjAcqThread; + GX_DEV_HANDLE m_hDevice; ///< Device Handle + uint32_t m_ui32DeviceNum; ///< Device number enumerated - IrisCameraCapEventHandler * irisCamHandler; + bool m_bOpen; ///< Flag : camera is opened or not + bool m_bAcquisitionStart; ///< Flag : camera is acquiring or not private: - GxIAPICPP::gxdeviceinfo_vector irisCamList; - - CGXDevicePointer irisCamPtr; ///< 设备句柄 - - CGXStreamPointer irisStreamPtr; ///< 左眼设备流 - - CGXFeatureControlPointer irisFeaturePtr; ///< 左眼属性控制器 - - CGXFeatureControlPointer irisStreamFeaturePtr; ///< 左眼流层控制器对象 - - void OpenDevice(); + // 初始化并打开人脸相机 + void initIrisCameraController(); + void SetUpAcquisitionThread(); + void UpdateDeviceList(); + bool SetAcquisitionBufferNum(); + void StartAcquisition(); + void StopAcquisition(); signals: - -public slots: - void getOneFaceFrm(); - + void irisCameraInitError(); + void irisCameraTermError(); }; #endif // IRISCAMERACONTROLLER_H diff --git a/device/device.pri b/device/device.pri index d1330a0..583721b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,13 +1,14 @@ HEADERS += $$PWD/IrisCameraController.h -HEADERS += $$PWD/IrisCameraCapEventHandler.h -#HEADERS += $$PWD/iris/IrisRegistProcess.h +#HEADERS += $$PWD/IrisCameraCapEventHandler.h +HEADERS += $$PWD/Common.h +HEADERS += $$PWD/AcquisitionThread.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h SOURCES += $$PWD/IrisCameraController.cpp -SOURCES += $$PWD/IrisCameraCapEventHandler.cpp -#SOURCES += $$PWD/iris/IrisRegistProcess.cpp +#SOURCES += $$PWD/IrisCameraCapEventHandler.cpp +SOURCES += $$PWD/AcquisitionThread.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 38f54fe..e4c8a02 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -11,7 +11,7 @@ // 连接算法服务 clientUtil = new SocketClientUtil(this); - clientUtil->connect("192.168.83.223", 50007); + clientUtil->connect(SettingConfig::getInstance().DEBUG_SEGMENT_IP, 50007); // 调用socket发送消息 connect(this, &IrisRecogProcess::sendDataToExract, clientUtil, &SocketClientUtil::sendData); @@ -43,18 +43,18 @@ continue; } - // 1. 图像栈中没有图像则直接返回 - if (ProMemory::getInstance().isIrisQueueEmpty() == true) + // 1. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 + if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) { - qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); + qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } - // 2. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 - if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) + // 2. 图像栈中没有图像则直接返回 + if (ProMemory::getInstance().isIrisQueueEmpty() == true) { - qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); + qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } @@ -73,7 +73,7 @@ int findEyeLast = timer.elapsed(); qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); -// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.matData = cv::imread("/home/casic/code/irisLogs/145333.552.bmp", 0); // irisInfo.hasEye = true; // 4.1 没有找到眼睛则返回 @@ -117,11 +117,10 @@ // 缩放到320 * 240 cv::resize(segMat, segMat, cv::Size(SettingConfig::getInstance().IRIS_WIDTH * 0.5, SettingConfig::getInstance().IRIS_HEIGHT * 0.5)); - - // std::string filename = QString("%1\\%2\\%3-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - // cv::imwrite(filename, segMat); - // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - +/* + std::string filename = QString("%1/%2/%3-seg.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(filename, segMat); +*/ int segMatSize = segMat.cols * segMat.rows; QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 @@ -167,9 +166,9 @@ // 成功接收后清除缓存区 clientUtil->resetRecvBuffer(); /* - std::string pupilSeg = QString("%1\\%2\\%3-pupil-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string maskSeg = QString("%1\\%2\\%3-mask-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string irisSeg = QString("%1\\%2\\%3-iris-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string pupilSeg = QString("%1/%2/%3-pupil-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); cv::imwrite(pupilSeg, pupil); cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); @@ -196,12 +195,20 @@ CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; irisInfo = casic::iris::CasicIrisInterface::getInstance().irisEncode(irisInfo); /* - std::string codeFilename = QString("%1\\%2\\%3-code.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string codeFilename = QString("%1/%2/%3-code.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string maskFilename = QString("%1/%2/%3-mask.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); */ + if (irisInfo.postProcSucc == false) { + qDebug() << "算法post process失败,暂停200ms"; + + addOneTryCount(); + this->msleep(THREAD_MSLEEP); // 200ms后再判断 + continue; + } + // 从编码中提取特征值 irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); @@ -211,6 +218,8 @@ CasicIrisRecState::getInstance().extractTmLast = encodeLast; CasicIrisRecState::getInstance().recogTimeLast += encodeLast; +// cv::imwrite(QString("%1/%2/%3.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(), irisInfo.matData); + // 开始匹配 timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) @@ -219,7 +228,7 @@ float score = casic::iris::CasicIrisInterface::getInstance().calculatePairPoints(feature.irisFeatureCode, irisInfo.irisFeatureCode); // 计算压缩编码的比较值 -// cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); +// cv::imwrite(QString("%1/%2/%3-%4.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; @@ -251,7 +260,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } @@ -268,7 +277,7 @@ CasicIrisRecState::getInstance().tryCount = 0; this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); emit failedMatchedIris(); @@ -290,7 +299,7 @@ // 识别失败时暂停工作 待返回识别界面时再开始工作和拍图 this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); } } else if (ProMemory::getInstance().appState == AppConstants::ApplicationState::STATE_WORKING) @@ -298,7 +307,8 @@ CasicIrisRecState::getInstance().noEyeCount++; // 如果在工作状态 则超过一定次数后返回待机 - if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT) + if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT && + SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT > 0) { // 发送信号待机 emit backToLockScreen(); diff --git a/device/iris/IrisRecogProcess.h b/device/iris/IrisRecogProcess.h index 9a3eec6..e21c1a7 100644 --- a/device/iris/IrisRecogProcess.h +++ b/device/iris/IrisRecogProcess.h @@ -1,4 +1,4 @@ -#ifndef IRISRECOGPROCESS_H +#ifndef IRISRECOGPROCESS_H #define IRISRECOGPROCESS_H #define THREAD_MSLEEP 200 @@ -10,6 +10,7 @@ #include "ProMemory.h" #include "device/iris/CasicIrisRecState.h" +#include "casic/iris/CasicIrisInterface.h" class IrisRecogProcess : public QThread { diff --git a/main.cpp b/main.cpp index 9052ddb..3bfb1c6 100644 --- a/main.cpp +++ b/main.cpp @@ -1,11 +1,11 @@ -#include "MainWindowForm.h" - -#include - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - MainWindowForm w; - w.show(); - return a.exec(); -} +#include "MainWindowForm.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindowForm w; + w.show(); + return a.exec(); +} diff --git a/utils/ImageUtil.cpp b/utils/ImageUtil.cpp index ff77331..d40ea79 100644 --- a/utils/ImageUtil.cpp +++ b/utils/ImageUtil.cpp @@ -1,107 +1,107 @@ -#include "ImageUtil.h" - -ImageUtil::ImageUtil() -{ - -} - -QImage ImageUtil::MatImageToQImage(const cv::Mat &src) -{ - //CV_8UC1 8位无符号的单通道---灰度图片 - if(src.type() == CV_8UC1) - { - QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); - return qImage; - } - //为3通道的彩色图片 - else if(src.type() == CV_8UC3) - { - //得到图像的的首地址 - const uchar *pSrc = (const uchar*)src.data; - //以src构造图片 - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); - } - //四通道图片, 带Alpha通道的RGB彩色图像 - else if(src.type() == CV_8UC4) - { - const uchar *pSrc = (const uchar*)src.data; - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); - //返回图像的子区域作为一个新图像 - return qImage.copy(); - } - else - { - return QImage(); - } -} - -cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) -{ - cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); - return img; -} - -cv::Mat ImageUtil::QImageToMat(QImage image) -{ - cv::Mat mat; - switch(image.format()) - { - case QImage::Format_ARGB32: - case QImage::Format_RGB32: - case QImage::Format_ARGB32_Premultiplied: - mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_RGB888: - mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); - cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); - break; - case QImage::Format_Indexed8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_Grayscale8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); - break; - - default: - break; - } - - mat = mat.clone(); - - return mat; -} - -/* -QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) -{ - QImage qImage(data, width, height, format); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); -} - -QString ImageUtil::QImageToBase64(QImage image) -{ - QByteArray ba; - QBuffer buf(&ba); - image.save(&buf, "bmp"); - QString base64String = ba.toBase64(); - return base64String; -} - -cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) -{ - cv::Mat matClone = src.clone(); - cv::Rect bigRect; - - bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; - bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; - bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; - bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; - - cv::Mat roi = matClone(bigRect); - - return roi; -} -*/ +#include "ImageUtil.h" + +ImageUtil::ImageUtil() +{ + +} + +QImage ImageUtil::MatImageToQImage(const cv::Mat &src) +{ + //CV_8UC1 8位无符号的单通道---灰度图片 + if(src.type() == CV_8UC1) + { + QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); + return qImage; + } + //为3通道的彩色图片 + else if(src.type() == CV_8UC3) + { + //得到图像的的首地址 + const uchar *pSrc = (const uchar*)src.data; + //以src构造图片 + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); + } + //四通道图片, 带Alpha通道的RGB彩色图像 + else if(src.type() == CV_8UC4) + { + const uchar *pSrc = (const uchar*)src.data; + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); + //返回图像的子区域作为一个新图像 + return qImage.copy(); + } + else + { + return QImage(); + } +} + +cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) +{ + cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); + return img; +} + +cv::Mat ImageUtil::QImageToMat(QImage image) +{ + cv::Mat mat; + switch(image.format()) + { + case QImage::Format_ARGB32: + case QImage::Format_RGB32: + case QImage::Format_ARGB32_Premultiplied: + mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_RGB888: + mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); + cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); + break; + case QImage::Format_Indexed8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_Grayscale8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); + break; + + default: + break; + } + + mat = mat.clone(); + + return mat; +} + +/* +QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) +{ + QImage qImage(data, width, height, format); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); +} + +QString ImageUtil::QImageToBase64(QImage image) +{ + QByteArray ba; + QBuffer buf(&ba); + image.save(&buf, "bmp"); + QString base64String = ba.toBase64(); + return base64String; +} + +cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) +{ + cv::Mat matClone = src.clone(); + cv::Rect bigRect; + + bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; + bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; + bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; + bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; + + cv::Mat roi = matClone(bigRect); + + return roi; +} +*/ diff --git a/utils/ImageUtil.h b/utils/ImageUtil.h index d9bf00a..4b702f4 100644 --- a/utils/ImageUtil.h +++ b/utils/ImageUtil.h @@ -1,23 +1,23 @@ -#ifndef IMAGEUTIL_H -#define IMAGEUTIL_H - -#include -#include -#include "opencv2/opencv.hpp" - -class ImageUtil -{ -public: - ImageUtil(); - - static QImage MatImageToQImage(const cv::Mat &src); -// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); - - static cv::Mat ucharToMat(unsigned char * data, int row, int col); - static cv::Mat QImageToMat(QImage image); -// static QString QImageToBase64(QImage image); - -// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); -}; - -#endif // IMAGEUTIL_H +#ifndef IMAGEUTIL_H +#define IMAGEUTIL_H + +#include +#include +#include "opencv2/opencv.hpp" + +class ImageUtil +{ +public: + ImageUtil(); + + static QImage MatImageToQImage(const cv::Mat &src); +// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); + + static cv::Mat ucharToMat(unsigned char * data, int row, int col); + static cv::Mat QImageToMat(QImage image); +// static QString QImageToBase64(QImage image); + +// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); +}; + +#endif // IMAGEUTIL_H diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp index 663db0f..05c4c68 100644 --- a/utils/SettingConfig.cpp +++ b/utils/SettingConfig.cpp @@ -1,4 +1,4 @@ -#include "SettingConfig.h" +#include "SettingConfig.h" #include SettingConfig::SettingConfig() @@ -34,6 +34,9 @@ LOG_FILE = getProperty("log", "logFile").toString(); LOG_LEVEL = getProperty("log", "logLevel").toString(); + + DEBUG_CAMERA_ROTATE = getProperty("debug", "cameraRotate").toString(); + DEBUG_SEGMENT_IP = getProperty("debug", "segmentIp").toString(); } diff --git a/utils/SettingConfig.h b/utils/SettingConfig.h index b65f553..c35d6ab 100644 --- a/utils/SettingConfig.h +++ b/utils/SettingConfig.h @@ -1,4 +1,4 @@ -#ifndef SETTINGCONFIG_H +#ifndef SETTINGCONFIG_H #define SETTINGCONFIG_H #include @@ -55,6 +55,9 @@ QString LOG_FILE; QString LOG_LEVEL; + QString DEBUG_CAMERA_ROTATE; + QString DEBUG_SEGMENT_IP; + private: SettingConfig(); diff --git a/utils/SocketClientUtil.cpp b/utils/SocketClientUtil.cpp index d539d64..20b8869 100644 --- a/utils/SocketClientUtil.cpp +++ b/utils/SocketClientUtil.cpp @@ -1,9 +1,10 @@ -#include "SocketClientUtil.h" +#include "SocketClientUtil.h" #include "utils/ByteUtil.h" SocketClientUtil::SocketClientUtil(QObject *parent) : QObject(parent) { QObject::connect(&objClient, &QTcpSocket::readyRead, this, &SocketClientUtil::readData); + QObject::connect(&objClient, &QTcpSocket::disconnected, this, &SocketClientUtil::socketReconnect); } void SocketClientUtil::connect(QString host, int port) @@ -16,6 +17,10 @@ void SocketClientUtil::closeConnect() { + QObject::disconnect(&objClient, &QTcpSocket::readyRead, this, &SocketClientUtil::readData); + QObject::disconnect(&objClient, &QTcpSocket::disconnected, this, &SocketClientUtil::socketReconnect); + + objClient.disconnectFromHost(); objClient.close(); } @@ -45,3 +50,9 @@ emit this->responseReaded(); } } + +void SocketClientUtil::socketReconnect() +{ + objClient.close(); + objClient.connectToHost(this->host, this->port); +} diff --git a/utils/SocketClientUtil.h b/utils/SocketClientUtil.h index 96b60e0..8bd1b8c 100644 --- a/utils/SocketClientUtil.h +++ b/utils/SocketClientUtil.h @@ -1,4 +1,4 @@ -#ifndef SOCKETCLIENTUTIL_H +#ifndef SOCKETCLIENTUTIL_H #define SOCKETCLIENTUTIL_H #include @@ -30,6 +30,7 @@ public slots: void readData(); void sendData(QByteArray data); + void socketReconnect(); }; diff --git a/utils/TimeCounterUtil.cpp b/utils/TimeCounterUtil.cpp index 275945f..78c3d69 100644 --- a/utils/TimeCounterUtil.cpp +++ b/utils/TimeCounterUtil.cpp @@ -1,8 +1,9 @@ -#include "TimeCounterUtil.h" - -TimeCounterUtil::TimeCounterUtil() -{ - faceCapCounter = new QTimer(); - irisCapCounter = new QTimer(); - clockCounter = new QTimer(); -} +#include "TimeCounterUtil.h" + +TimeCounterUtil::TimeCounterUtil() +{ + faceCapCounter = new QTimer(); + irisCapCounter = new QTimer(); + clockCounter = new QTimer(); + videoCounter = new QTimer(); +} diff --git a/utils/TimeCounterUtil.h b/utils/TimeCounterUtil.h index 28b29f1..91f8da0 100644 --- a/utils/TimeCounterUtil.h +++ b/utils/TimeCounterUtil.h @@ -1,29 +1,30 @@ -#ifndef TIMECOUNTERUTIL_H -#define TIMECOUNTERUTIL_H - -#include -#include - -class TimeCounterUtil : public QObject -{ -public: - - ~TimeCounterUtil() {}; - TimeCounterUtil(const TimeCounterUtil&)=delete; - TimeCounterUtil& operator=(const TimeCounterUtil&)=delete; - - static TimeCounterUtil& getInstance() { - static TimeCounterUtil instance; - return instance; - } - - QTimer * faceCapCounter; - QTimer * irisCapCounter; - QTimer * clockCounter; - -private: - TimeCounterUtil(); - -}; - -#endif // TIMECOUNTERUTIL_H +#ifndef TIMECOUNTERUTIL_H +#define TIMECOUNTERUTIL_H + +#include +#include + +class TimeCounterUtil : public QObject +{ +public: + + ~TimeCounterUtil() {}; + TimeCounterUtil(const TimeCounterUtil&)=delete; + TimeCounterUtil& operator=(const TimeCounterUtil&)=delete; + + static TimeCounterUtil& getInstance() { + static TimeCounterUtil instance; + return instance; + } + + QTimer * faceCapCounter; + QTimer * irisCapCounter; + QTimer * clockCounter; + QTimer * videoCounter; // show video images on main window + +private: + TimeCounterUtil(); + +}; + +#endif // TIMECOUNTERUTIL_H diff --git a/utils/UtilInclude.h b/utils/UtilInclude.h index 0b329c9..bea17be 100644 --- a/utils/UtilInclude.h +++ b/utils/UtilInclude.h @@ -1,15 +1,15 @@ -#ifndef UTILINCLUDE_H -#define UTILINCLUDE_H - -#include -#include "ByteUtil.h" -#include "ImageUtil.h" -#include "LogUtil.h" -#include "SettingConfig.h" -#include "SocketClientUtil.h" -#include "SpeakerUtil.h" -#include "TimeCounterUtil.h" -//#include "UDPClientUtil.h" -//#include "HttpRequestUtil.h" - -#endif // UTILINCLUDE_H +#ifndef UTILINCLUDE_H +#define UTILINCLUDE_H + +#include +#include "ByteUtil.h" +#include "ImageUtil.h" +#include "LogUtil.h" +#include "SettingConfig.h" +#include "SocketClientUtil.h" +#include "SpeakerUtil.h" +#include "TimeCounterUtil.h" +//#include "UDPClientUtil.h" +//#include "HttpRequestUtil.h" + +#endif // UTILINCLUDE_H diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/device/IrisCameraCapEventHandler.h b/device/IrisCameraCapEventHandler.h index 8b976c5..94f5594 100644 --- a/device/IrisCameraCapEventHandler.h +++ b/device/IrisCameraCapEventHandler.h @@ -1,10 +1,9 @@ -#ifndef IRISCAMERACAPEVENTHANDLER_H +#ifndef IRISCAMERACAPEVENTHANDLER_H #define IRISCAMERACAPEVENTHANDLER_H #include #include -#include "include/opencv2/opencv.hpp" -#include "include/daheng/GalaxyIncludes.h" +#include #include "casic/iris/CasicIrisInterface.h" #include "ProMemory.h" diff --git a/device/IrisCameraController.cpp b/device/IrisCameraController.cpp index 0928176..4eea013 100644 --- a/device/IrisCameraController.cpp +++ b/device/IrisCameraController.cpp @@ -1,8 +1,8 @@ -#include "IrisCameraController.h" +#include "IrisCameraController.h" IrisCameraController::IrisCameraController(QObject *parent) : QObject(parent) { - this->irisCamHandler = new IrisCameraCapEventHandler(this); + initIrisCameraController(); } IrisCameraController::~IrisCameraController() { @@ -10,101 +10,204 @@ } -void IrisCameraController::initIrisCamera() +void IrisCameraController::initIrisCameraController() { - IGXFactory::GetInstance().Init(); + // Init GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXInitLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraInitError(); + LOG_ERROR("[CameraController]初始化虹膜相机失败"); + return ; + } + LOG_INFO("[CameraController]初始化虹膜相机成功"); //枚举设备 - IGXFactory::GetInstance().UpdateDeviceList(1000, irisCamList); - - this->OpenDevice(); + UpdateDeviceList(); } void IrisCameraController::openIrisCamera() { - //设置Buffer处理模式 - irisStreamFeaturePtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst"); + GX_STATUS emStatus = GX_STATUS_SUCCESS; - //注册回调函数 - irisStreamPtr->RegisterCaptureCallback(irisCamHandler, &irisCamPtr); + if (m_ui32DeviceNum > 0) { + emStatus = GXOpenDeviceByIndex(1, &m_hDevice); - //开启流层通道 - irisStreamPtr->StartGrab(); + if (emStatus == GX_STATUS_SUCCESS) { + LOG_INFO("[CameraController]开启虹膜相机成功"); - //发送开采命令 - irisFeaturePtr->GetCommandFeature("AcquisitionStart")->Execute(); + // isOpen flag set true + m_bOpen = true; - // 启动定时器 - TimeCounterUtil::getInstance().irisCapCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); // 50ms执行一次定时器 + SetUpAcquisitionThread(); + } + } + + return; } void IrisCameraController::closeIrisCamera() { - + // Release GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXCloseLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraTermError(); + } } void IrisCameraController::startCapture() { // 获取定时器, 绑定定时函数 - connect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString()); + bool bSetDone = false; + // Set acquisition buffer number + bSetDone = SetAcquisitionBufferNum(); + if (!bSetDone) + { + return; + } + + bool bPrepareDone = false; + // Alloc resource for image acquisition + bPrepareDone = m_pobjAcqThread->PrepareForShowImg(); + if (!bPrepareDone) + { + return; + } + + // Device start acquisition and start acquisition thread + StartAcquisition(); + + LOG_DEBUG(QString("[CameraController][startCapture]虹膜相机拍图").toStdString()); + + // Do not start timer when acquisition start failed + if (!m_bAcquisitionStart) + { + return; + } } void IrisCameraController::stopCapture() { - // 获取定时器, 绑定定时函数 - disconnect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString()); - + this->StopAcquisition(); } -void IrisCameraController::getOneFaceFrm() +void IrisCameraController::SetUpAcquisitionThread() { - // 发送软触发命令(在触发模式开启时有效) - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::getLeftAndRightEyeFrame() -{ - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::OpenDevice() -{ - auto device = irisCamList.at(0); - - irisCamPtr = IGXFactory::GetInstance().OpenDeviceByUserID(device.GetUserID(), GX_ACCESS_EXCLUSIVE); - irisFeaturePtr = irisCamPtr->GetRemoteFeatureControl(); - - // 判断设备流是否大于零, 如果大于零则打开流 - int nStreamCount = irisCamPtr->GetStreamCount(); - if (nStreamCount > 0) + // if Acquisition thread is on Stop acquisition thread + if (m_pobjAcqThread != NULL) { - irisStreamPtr = irisCamPtr->OpenStream(0); - irisStreamFeaturePtr = irisStreamPtr->GetFeatureControl(); + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Release acquisition thread object + RELEASE_ALLOC_MEM(m_pobjAcqThread); } - // 建议用户在打开网络相机之后, 根据当前网络环境设置相机的流通道包长值, - // 以提高网络相机的采集性能, 设置方法参考以下代码。 - GX_DEVICE_CLASS_LIST objDeviceClass = irisCamPtr->GetDeviceInfo().GetDeviceClass(); - if(GX_DEVICE_CLASS_GEV == objDeviceClass) + // Instantiation acquisition thread + try { - // 判断设备是否支持流通道数据包功能 - if(true == irisFeaturePtr->IsImplemented("GevSCPSPacketSize")) - { - // 获取当前网络环境的最优包长值 - int nPacketSize = irisStreamPtr->GetOptimalPacketSize(); - // 将最优包长值设置为当前设备的流通道包长值 - irisFeaturePtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize); - } + m_pobjAcqThread = new CAcquisitionThread(); + m_pobjAcqThread->m_hDevice = m_hDevice; + } + catch (std::bad_alloc &e) + { + QMessageBox::about(NULL, "Allocate memory error", "Cannot allocate memory, please exit this app!"); + RELEASE_ALLOC_MEM(m_pobjAcqThread); + return; } - //设置采集模式为连续采集模式 - irisFeaturePtr->GetEnumFeature("AcquisitionMode")->SetValue("Continuous"); + return; +} - //设置触发模式关 - irisFeaturePtr->GetEnumFeature("TriggerMode")->SetValue("On"); - irisFeaturePtr->GetEnumFeature("TriggerSource")->SetValue("Software"); +void IrisCameraController::UpdateDeviceList() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Enumerate Devcie List + emStatus = GXUpdateDeviceList(&m_ui32DeviceNum, ENUMRATE_TIME_OUT); + + LOG_INFO(QString("[CameraController]枚举虹膜相机成功[%1]").arg(m_ui32DeviceNum).toStdString()); + + return; +} + +void IrisCameraController::StartAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + emStatus = GXStreamOn(m_hDevice); + + // Set acquisition thread run flag + m_pobjAcqThread->m_bAcquisitionThreadFlag = true; + + // Acquisition thread start + m_pobjAcqThread->start(); + + // isStart flag set true + m_bAcquisitionStart = true; + + return; +} + +void IrisCameraController::StopAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Turn off stream + emStatus = GXStreamOff(m_hDevice); + + // isStart flag set false + m_bAcquisitionStart = false; + + return; +} + +bool IrisCameraController::SetAcquisitionBufferNum() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + uint64_t ui64BufferNum = 0; + int64_t i64PayloadSize = 0; + + // Get device current payload size + emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &i64PayloadSize); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Set buffer quantity of acquisition queue + if (i64PayloadSize == 0) + { + return false; + } + + // Calculate a reasonable number of Buffers for different payload size + // Small ROI and high frame rate will requires more acquisition Buffer + const size_t MAX_MEMORY_SIZE = 8 * 1024 * 1024; // The maximum number of memory bytes available for allocating frame Buffer + const size_t MIN_BUFFER_NUM = 5; // Minimum frame Buffer number + const size_t MAX_BUFFER_NUM = 450; // Maximum frame Buffer number + ui64BufferNum = MAX_MEMORY_SIZE / i64PayloadSize; + ui64BufferNum = (ui64BufferNum <= MIN_BUFFER_NUM) ? MIN_BUFFER_NUM : ui64BufferNum; + ui64BufferNum = (ui64BufferNum >= MAX_BUFFER_NUM) ? MAX_BUFFER_NUM : ui64BufferNum; + + emStatus = GXSetAcqusitionBufferNumber(m_hDevice, ui64BufferNum); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Transfer buffer number to acquisition thread class for using GXDQAllBufs + m_pobjAcqThread->m_ui64AcquisitionBufferNum = ui64BufferNum; + + return true; } diff --git a/device/IrisCameraController.h b/device/IrisCameraController.h index 5d7e269..67cbe2f 100644 --- a/device/IrisCameraController.h +++ b/device/IrisCameraController.h @@ -1,11 +1,12 @@ -#ifndef IRISCAMERACONTROLLER_H +#ifndef IRISCAMERACONTROLLER_H #define IRISCAMERACONTROLLER_H #include -#include "IrisCameraCapEventHandler.h" +#include "AcquisitionThread.h" +#include "utils/UtilInclude.h" -class IrisCameraCapEventHandler; +#define ENUMRATE_TIME_OUT 200 class IrisCameraController : public QObject { @@ -14,36 +15,31 @@ explicit IrisCameraController(QObject *parent = nullptr); ~IrisCameraController(); - // 初始化并打开人脸相机 - void initIrisCamera(); void openIrisCamera(); void closeIrisCamera(); void startCapture(); void stopCapture(); - void getLeftAndRightEyeFrame(); + CAcquisitionThread * m_pobjAcqThread; + GX_DEV_HANDLE m_hDevice; ///< Device Handle + uint32_t m_ui32DeviceNum; ///< Device number enumerated - IrisCameraCapEventHandler * irisCamHandler; + bool m_bOpen; ///< Flag : camera is opened or not + bool m_bAcquisitionStart; ///< Flag : camera is acquiring or not private: - GxIAPICPP::gxdeviceinfo_vector irisCamList; - - CGXDevicePointer irisCamPtr; ///< 设备句柄 - - CGXStreamPointer irisStreamPtr; ///< 左眼设备流 - - CGXFeatureControlPointer irisFeaturePtr; ///< 左眼属性控制器 - - CGXFeatureControlPointer irisStreamFeaturePtr; ///< 左眼流层控制器对象 - - void OpenDevice(); + // 初始化并打开人脸相机 + void initIrisCameraController(); + void SetUpAcquisitionThread(); + void UpdateDeviceList(); + bool SetAcquisitionBufferNum(); + void StartAcquisition(); + void StopAcquisition(); signals: - -public slots: - void getOneFaceFrm(); - + void irisCameraInitError(); + void irisCameraTermError(); }; #endif // IRISCAMERACONTROLLER_H diff --git a/device/device.pri b/device/device.pri index d1330a0..583721b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,13 +1,14 @@ HEADERS += $$PWD/IrisCameraController.h -HEADERS += $$PWD/IrisCameraCapEventHandler.h -#HEADERS += $$PWD/iris/IrisRegistProcess.h +#HEADERS += $$PWD/IrisCameraCapEventHandler.h +HEADERS += $$PWD/Common.h +HEADERS += $$PWD/AcquisitionThread.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h SOURCES += $$PWD/IrisCameraController.cpp -SOURCES += $$PWD/IrisCameraCapEventHandler.cpp -#SOURCES += $$PWD/iris/IrisRegistProcess.cpp +#SOURCES += $$PWD/IrisCameraCapEventHandler.cpp +SOURCES += $$PWD/AcquisitionThread.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 38f54fe..e4c8a02 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -11,7 +11,7 @@ // 连接算法服务 clientUtil = new SocketClientUtil(this); - clientUtil->connect("192.168.83.223", 50007); + clientUtil->connect(SettingConfig::getInstance().DEBUG_SEGMENT_IP, 50007); // 调用socket发送消息 connect(this, &IrisRecogProcess::sendDataToExract, clientUtil, &SocketClientUtil::sendData); @@ -43,18 +43,18 @@ continue; } - // 1. 图像栈中没有图像则直接返回 - if (ProMemory::getInstance().isIrisQueueEmpty() == true) + // 1. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 + if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) { - qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); + qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } - // 2. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 - if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) + // 2. 图像栈中没有图像则直接返回 + if (ProMemory::getInstance().isIrisQueueEmpty() == true) { - qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); + qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } @@ -73,7 +73,7 @@ int findEyeLast = timer.elapsed(); qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); -// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.matData = cv::imread("/home/casic/code/irisLogs/145333.552.bmp", 0); // irisInfo.hasEye = true; // 4.1 没有找到眼睛则返回 @@ -117,11 +117,10 @@ // 缩放到320 * 240 cv::resize(segMat, segMat, cv::Size(SettingConfig::getInstance().IRIS_WIDTH * 0.5, SettingConfig::getInstance().IRIS_HEIGHT * 0.5)); - - // std::string filename = QString("%1\\%2\\%3-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - // cv::imwrite(filename, segMat); - // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - +/* + std::string filename = QString("%1/%2/%3-seg.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(filename, segMat); +*/ int segMatSize = segMat.cols * segMat.rows; QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 @@ -167,9 +166,9 @@ // 成功接收后清除缓存区 clientUtil->resetRecvBuffer(); /* - std::string pupilSeg = QString("%1\\%2\\%3-pupil-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string maskSeg = QString("%1\\%2\\%3-mask-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string irisSeg = QString("%1\\%2\\%3-iris-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string pupilSeg = QString("%1/%2/%3-pupil-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); cv::imwrite(pupilSeg, pupil); cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); @@ -196,12 +195,20 @@ CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; irisInfo = casic::iris::CasicIrisInterface::getInstance().irisEncode(irisInfo); /* - std::string codeFilename = QString("%1\\%2\\%3-code.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string codeFilename = QString("%1/%2/%3-code.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string maskFilename = QString("%1/%2/%3-mask.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); */ + if (irisInfo.postProcSucc == false) { + qDebug() << "算法post process失败,暂停200ms"; + + addOneTryCount(); + this->msleep(THREAD_MSLEEP); // 200ms后再判断 + continue; + } + // 从编码中提取特征值 irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); @@ -211,6 +218,8 @@ CasicIrisRecState::getInstance().extractTmLast = encodeLast; CasicIrisRecState::getInstance().recogTimeLast += encodeLast; +// cv::imwrite(QString("%1/%2/%3.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(), irisInfo.matData); + // 开始匹配 timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) @@ -219,7 +228,7 @@ float score = casic::iris::CasicIrisInterface::getInstance().calculatePairPoints(feature.irisFeatureCode, irisInfo.irisFeatureCode); // 计算压缩编码的比较值 -// cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); +// cv::imwrite(QString("%1/%2/%3-%4.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; @@ -251,7 +260,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } @@ -268,7 +277,7 @@ CasicIrisRecState::getInstance().tryCount = 0; this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); emit failedMatchedIris(); @@ -290,7 +299,7 @@ // 识别失败时暂停工作 待返回识别界面时再开始工作和拍图 this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); } } else if (ProMemory::getInstance().appState == AppConstants::ApplicationState::STATE_WORKING) @@ -298,7 +307,8 @@ CasicIrisRecState::getInstance().noEyeCount++; // 如果在工作状态 则超过一定次数后返回待机 - if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT) + if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT && + SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT > 0) { // 发送信号待机 emit backToLockScreen(); diff --git a/device/iris/IrisRecogProcess.h b/device/iris/IrisRecogProcess.h index 9a3eec6..e21c1a7 100644 --- a/device/iris/IrisRecogProcess.h +++ b/device/iris/IrisRecogProcess.h @@ -1,4 +1,4 @@ -#ifndef IRISRECOGPROCESS_H +#ifndef IRISRECOGPROCESS_H #define IRISRECOGPROCESS_H #define THREAD_MSLEEP 200 @@ -10,6 +10,7 @@ #include "ProMemory.h" #include "device/iris/CasicIrisRecState.h" +#include "casic/iris/CasicIrisInterface.h" class IrisRecogProcess : public QThread { diff --git a/main.cpp b/main.cpp index 9052ddb..3bfb1c6 100644 --- a/main.cpp +++ b/main.cpp @@ -1,11 +1,11 @@ -#include "MainWindowForm.h" - -#include - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - MainWindowForm w; - w.show(); - return a.exec(); -} +#include "MainWindowForm.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindowForm w; + w.show(); + return a.exec(); +} diff --git a/utils/ImageUtil.cpp b/utils/ImageUtil.cpp index ff77331..d40ea79 100644 --- a/utils/ImageUtil.cpp +++ b/utils/ImageUtil.cpp @@ -1,107 +1,107 @@ -#include "ImageUtil.h" - -ImageUtil::ImageUtil() -{ - -} - -QImage ImageUtil::MatImageToQImage(const cv::Mat &src) -{ - //CV_8UC1 8位无符号的单通道---灰度图片 - if(src.type() == CV_8UC1) - { - QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); - return qImage; - } - //为3通道的彩色图片 - else if(src.type() == CV_8UC3) - { - //得到图像的的首地址 - const uchar *pSrc = (const uchar*)src.data; - //以src构造图片 - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); - } - //四通道图片, 带Alpha通道的RGB彩色图像 - else if(src.type() == CV_8UC4) - { - const uchar *pSrc = (const uchar*)src.data; - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); - //返回图像的子区域作为一个新图像 - return qImage.copy(); - } - else - { - return QImage(); - } -} - -cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) -{ - cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); - return img; -} - -cv::Mat ImageUtil::QImageToMat(QImage image) -{ - cv::Mat mat; - switch(image.format()) - { - case QImage::Format_ARGB32: - case QImage::Format_RGB32: - case QImage::Format_ARGB32_Premultiplied: - mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_RGB888: - mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); - cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); - break; - case QImage::Format_Indexed8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_Grayscale8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); - break; - - default: - break; - } - - mat = mat.clone(); - - return mat; -} - -/* -QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) -{ - QImage qImage(data, width, height, format); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); -} - -QString ImageUtil::QImageToBase64(QImage image) -{ - QByteArray ba; - QBuffer buf(&ba); - image.save(&buf, "bmp"); - QString base64String = ba.toBase64(); - return base64String; -} - -cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) -{ - cv::Mat matClone = src.clone(); - cv::Rect bigRect; - - bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; - bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; - bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; - bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; - - cv::Mat roi = matClone(bigRect); - - return roi; -} -*/ +#include "ImageUtil.h" + +ImageUtil::ImageUtil() +{ + +} + +QImage ImageUtil::MatImageToQImage(const cv::Mat &src) +{ + //CV_8UC1 8位无符号的单通道---灰度图片 + if(src.type() == CV_8UC1) + { + QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); + return qImage; + } + //为3通道的彩色图片 + else if(src.type() == CV_8UC3) + { + //得到图像的的首地址 + const uchar *pSrc = (const uchar*)src.data; + //以src构造图片 + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); + } + //四通道图片, 带Alpha通道的RGB彩色图像 + else if(src.type() == CV_8UC4) + { + const uchar *pSrc = (const uchar*)src.data; + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); + //返回图像的子区域作为一个新图像 + return qImage.copy(); + } + else + { + return QImage(); + } +} + +cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) +{ + cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); + return img; +} + +cv::Mat ImageUtil::QImageToMat(QImage image) +{ + cv::Mat mat; + switch(image.format()) + { + case QImage::Format_ARGB32: + case QImage::Format_RGB32: + case QImage::Format_ARGB32_Premultiplied: + mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_RGB888: + mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); + cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); + break; + case QImage::Format_Indexed8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_Grayscale8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); + break; + + default: + break; + } + + mat = mat.clone(); + + return mat; +} + +/* +QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) +{ + QImage qImage(data, width, height, format); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); +} + +QString ImageUtil::QImageToBase64(QImage image) +{ + QByteArray ba; + QBuffer buf(&ba); + image.save(&buf, "bmp"); + QString base64String = ba.toBase64(); + return base64String; +} + +cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) +{ + cv::Mat matClone = src.clone(); + cv::Rect bigRect; + + bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; + bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; + bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; + bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; + + cv::Mat roi = matClone(bigRect); + + return roi; +} +*/ diff --git a/utils/ImageUtil.h b/utils/ImageUtil.h index d9bf00a..4b702f4 100644 --- a/utils/ImageUtil.h +++ b/utils/ImageUtil.h @@ -1,23 +1,23 @@ -#ifndef IMAGEUTIL_H -#define IMAGEUTIL_H - -#include -#include -#include "opencv2/opencv.hpp" - -class ImageUtil -{ -public: - ImageUtil(); - - static QImage MatImageToQImage(const cv::Mat &src); -// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); - - static cv::Mat ucharToMat(unsigned char * data, int row, int col); - static cv::Mat QImageToMat(QImage image); -// static QString QImageToBase64(QImage image); - -// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); -}; - -#endif // IMAGEUTIL_H +#ifndef IMAGEUTIL_H +#define IMAGEUTIL_H + +#include +#include +#include "opencv2/opencv.hpp" + +class ImageUtil +{ +public: + ImageUtil(); + + static QImage MatImageToQImage(const cv::Mat &src); +// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); + + static cv::Mat ucharToMat(unsigned char * data, int row, int col); + static cv::Mat QImageToMat(QImage image); +// static QString QImageToBase64(QImage image); + +// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); +}; + +#endif // IMAGEUTIL_H diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp index 663db0f..05c4c68 100644 --- a/utils/SettingConfig.cpp +++ b/utils/SettingConfig.cpp @@ -1,4 +1,4 @@ -#include "SettingConfig.h" +#include "SettingConfig.h" #include SettingConfig::SettingConfig() @@ -34,6 +34,9 @@ LOG_FILE = getProperty("log", "logFile").toString(); LOG_LEVEL = getProperty("log", "logLevel").toString(); + + DEBUG_CAMERA_ROTATE = getProperty("debug", "cameraRotate").toString(); + DEBUG_SEGMENT_IP = getProperty("debug", "segmentIp").toString(); } diff --git a/utils/SettingConfig.h b/utils/SettingConfig.h index b65f553..c35d6ab 100644 --- a/utils/SettingConfig.h +++ b/utils/SettingConfig.h @@ -1,4 +1,4 @@ -#ifndef SETTINGCONFIG_H +#ifndef SETTINGCONFIG_H #define SETTINGCONFIG_H #include @@ -55,6 +55,9 @@ QString LOG_FILE; QString LOG_LEVEL; + QString DEBUG_CAMERA_ROTATE; + QString DEBUG_SEGMENT_IP; + private: SettingConfig(); diff --git a/utils/SocketClientUtil.cpp b/utils/SocketClientUtil.cpp index d539d64..20b8869 100644 --- a/utils/SocketClientUtil.cpp +++ b/utils/SocketClientUtil.cpp @@ -1,9 +1,10 @@ -#include "SocketClientUtil.h" +#include "SocketClientUtil.h" #include "utils/ByteUtil.h" SocketClientUtil::SocketClientUtil(QObject *parent) : QObject(parent) { QObject::connect(&objClient, &QTcpSocket::readyRead, this, &SocketClientUtil::readData); + QObject::connect(&objClient, &QTcpSocket::disconnected, this, &SocketClientUtil::socketReconnect); } void SocketClientUtil::connect(QString host, int port) @@ -16,6 +17,10 @@ void SocketClientUtil::closeConnect() { + QObject::disconnect(&objClient, &QTcpSocket::readyRead, this, &SocketClientUtil::readData); + QObject::disconnect(&objClient, &QTcpSocket::disconnected, this, &SocketClientUtil::socketReconnect); + + objClient.disconnectFromHost(); objClient.close(); } @@ -45,3 +50,9 @@ emit this->responseReaded(); } } + +void SocketClientUtil::socketReconnect() +{ + objClient.close(); + objClient.connectToHost(this->host, this->port); +} diff --git a/utils/SocketClientUtil.h b/utils/SocketClientUtil.h index 96b60e0..8bd1b8c 100644 --- a/utils/SocketClientUtil.h +++ b/utils/SocketClientUtil.h @@ -1,4 +1,4 @@ -#ifndef SOCKETCLIENTUTIL_H +#ifndef SOCKETCLIENTUTIL_H #define SOCKETCLIENTUTIL_H #include @@ -30,6 +30,7 @@ public slots: void readData(); void sendData(QByteArray data); + void socketReconnect(); }; diff --git a/utils/TimeCounterUtil.cpp b/utils/TimeCounterUtil.cpp index 275945f..78c3d69 100644 --- a/utils/TimeCounterUtil.cpp +++ b/utils/TimeCounterUtil.cpp @@ -1,8 +1,9 @@ -#include "TimeCounterUtil.h" - -TimeCounterUtil::TimeCounterUtil() -{ - faceCapCounter = new QTimer(); - irisCapCounter = new QTimer(); - clockCounter = new QTimer(); -} +#include "TimeCounterUtil.h" + +TimeCounterUtil::TimeCounterUtil() +{ + faceCapCounter = new QTimer(); + irisCapCounter = new QTimer(); + clockCounter = new QTimer(); + videoCounter = new QTimer(); +} diff --git a/utils/TimeCounterUtil.h b/utils/TimeCounterUtil.h index 28b29f1..91f8da0 100644 --- a/utils/TimeCounterUtil.h +++ b/utils/TimeCounterUtil.h @@ -1,29 +1,30 @@ -#ifndef TIMECOUNTERUTIL_H -#define TIMECOUNTERUTIL_H - -#include -#include - -class TimeCounterUtil : public QObject -{ -public: - - ~TimeCounterUtil() {}; - TimeCounterUtil(const TimeCounterUtil&)=delete; - TimeCounterUtil& operator=(const TimeCounterUtil&)=delete; - - static TimeCounterUtil& getInstance() { - static TimeCounterUtil instance; - return instance; - } - - QTimer * faceCapCounter; - QTimer * irisCapCounter; - QTimer * clockCounter; - -private: - TimeCounterUtil(); - -}; - -#endif // TIMECOUNTERUTIL_H +#ifndef TIMECOUNTERUTIL_H +#define TIMECOUNTERUTIL_H + +#include +#include + +class TimeCounterUtil : public QObject +{ +public: + + ~TimeCounterUtil() {}; + TimeCounterUtil(const TimeCounterUtil&)=delete; + TimeCounterUtil& operator=(const TimeCounterUtil&)=delete; + + static TimeCounterUtil& getInstance() { + static TimeCounterUtil instance; + return instance; + } + + QTimer * faceCapCounter; + QTimer * irisCapCounter; + QTimer * clockCounter; + QTimer * videoCounter; // show video images on main window + +private: + TimeCounterUtil(); + +}; + +#endif // TIMECOUNTERUTIL_H diff --git a/utils/UtilInclude.h b/utils/UtilInclude.h index 0b329c9..bea17be 100644 --- a/utils/UtilInclude.h +++ b/utils/UtilInclude.h @@ -1,15 +1,15 @@ -#ifndef UTILINCLUDE_H -#define UTILINCLUDE_H - -#include -#include "ByteUtil.h" -#include "ImageUtil.h" -#include "LogUtil.h" -#include "SettingConfig.h" -#include "SocketClientUtil.h" -#include "SpeakerUtil.h" -#include "TimeCounterUtil.h" -//#include "UDPClientUtil.h" -//#include "HttpRequestUtil.h" - -#endif // UTILINCLUDE_H +#ifndef UTILINCLUDE_H +#define UTILINCLUDE_H + +#include +#include "ByteUtil.h" +#include "ImageUtil.h" +#include "LogUtil.h" +#include "SettingConfig.h" +#include "SocketClientUtil.h" +#include "SpeakerUtil.h" +#include "TimeCounterUtil.h" +//#include "UDPClientUtil.h" +//#include "HttpRequestUtil.h" + +#endif // UTILINCLUDE_H diff --git a/utils/id/IdWorker.h b/utils/id/IdWorker.h index 6c48aa9..079bbcb 100644 --- a/utils/id/IdWorker.h +++ b/utils/id/IdWorker.h @@ -1,218 +1,218 @@ -#ifndef _JW_CORE_ID_WORKER_H_ -#define _JW_CORE_ID_WORKER_H_ - -#include -#include -#include -#include -#include -#include "Noncopyable.h" -#include "Singleton.h" - -// 如果不使用 mutex, 则开启下面这个定义, 但是我发现, 还是开启 mutex 功能, 速度比较快 -// #define SNOWFLAKE_ID_WORKER_NO_LOCK - -namespace Jiawa { - - /** - * @brief 核心 - * 核心功能 - */ - namespace Core { - - /** - * @brief 分布式id生成类 - * https://segmentfault.com/a/1190000011282426 - * https://github.com/twitter/snowflake/blob/snowflake-2010/src/main/scala/com/twitter/service/snowflake/IdWorker.scala - * - * 64bit id: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 - * || || || | | | - * |└---------------------------时间戳--------------------------┘└中心-┘└机器-┘ └----序列号----┘ - * | - * 不用 - * SnowFlake的优点: 整体上按照时间自增排序, 并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分), 并且效率较高, 经测试, SnowFlake每秒能够产生26万ID左右. - */ - class SnowflakeIdWorker : private Noncopyable { - - // 实现单例 - friend class Singleton; - - public: - typedef unsigned int UInt; - typedef unsigned long long int UInt64; - -#ifdef SNOWFLAKE_ID_WORKER_NO_LOCK - typedef std::atomic AtomicUInt; - typedef std::atomic AtomicUInt64; -#else - typedef UInt AtomicUInt; - typedef UInt64 AtomicUInt64; -#endif - - void setWorkerId(UInt workerId) { - this->workerId = workerId; - } - - void setDatacenterId(UInt datacenterId) { - this->datacenterId = datacenterId; - } - - UInt64 getId() { - return nextId(); - } - - /** - * 获得下一个ID (该方法是线程安全的) - * - * @return SnowflakeId - */ - UInt64 nextId() { -#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK - std::unique_lock lock{ mutex }; - AtomicUInt64 timestamp{ 0 }; -#else - static AtomicUInt64 timestamp{ 0 }; -#endif - timestamp = timeGen(); - - // 如果当前时间小于上一次ID生成的时间戳, 说明系统时钟回退过这个时候应当抛出异常 - if (timestamp < lastTimestamp) { - std::ostringstream s; - s << "clock moved backwards. Refusing to generate id for " << lastTimestamp - timestamp << " milliseconds"; - throw std::exception(std::runtime_error(s.str())); - } - - if (lastTimestamp == timestamp) { - // 如果是同一时间生成的, 则进行毫秒内序列 - sequence = (sequence + 1) & sequenceMask; - if (0 == sequence) { - // 毫秒内序列溢出, 阻塞到下一个毫秒,获得新的时间戳 - timestamp = tilNextMillis(lastTimestamp); - } - } else { - sequence = 0; - } - -#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK - lastTimestamp = timestamp; -#else - lastTimestamp = timestamp.load(); -#endif - - // 移位并通过或运算拼到一起组成64位的ID - return ((timestamp - twepoch) << timestampLeftShift) - | (datacenterId << datacenterIdShift) - | (workerId << workerIdShift) - | sequence; - } - - protected: - SnowflakeIdWorker() : workerId(0), datacenterId(0), sequence(0), lastTimestamp(0) { } - - /** - * 返回以毫秒为单位的当前时间 - * - * @return 当前时间(毫秒) - */ - UInt64 timeGen() const { - auto t = std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()); - return t.time_since_epoch().count(); - } - - /** - * 阻塞到下一个毫秒, 直到获得新的时间戳 - * - * @param lastTimestamp 上次生成ID的时间截 - * @return 当前时间戳 - */ - UInt64 tilNextMillis(UInt64 lastTimestamp) const { - UInt64 timestamp = timeGen(); - while (timestamp <= lastTimestamp) { - timestamp = timeGen(); - } - return timestamp; - } - - private: - -#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK - std::mutex mutex; -#endif - - /** - * 开始时间截 (2018-01-01 00:00:00.000) - */ - const UInt64 twepoch = 1514736000000; - - /** - * 机器id所占的位数 - */ - const UInt workerIdBits = 5; - - /** - * 数据中心id所占的位数 - */ - const UInt datacenterIdBits = 5; - - /** - * 序列所占的位数 - */ - const UInt sequenceBits = 12; - - /** - * 机器ID向左移12位 - */ - const UInt workerIdShift = sequenceBits; - - /** - * 数据标识id向左移17位 - */ - const UInt datacenterIdShift = workerIdShift + workerIdBits; - - /** - * 时间截向左移22位 - */ - const UInt timestampLeftShift = datacenterIdShift + datacenterIdBits; - - /** - * 支持的最大机器id, 结果是31 - */ - const UInt maxWorkerId = -1 ^ (-1 << workerIdBits); - - /** - * 支持的最大数据中心id, 结果是31 - */ - const UInt maxDatacenterId = -1 ^ (-1 << datacenterIdBits); - - /** - * 生成序列的掩码, 这里为4095 - */ - const UInt sequenceMask = -1 ^ (-1 << sequenceBits); - - /** - * 工作机器id(0~31) - */ - UInt workerId; - - /** - * 数据中心id(0~31) - */ - UInt datacenterId; - - /** - * 毫秒内序列(0~4095) - */ - AtomicUInt sequence{ 0 }; - - /** - * 上次生成ID的时间截 - */ - AtomicUInt64 lastTimestamp{ 0 }; - - }; - - typedef SnowflakeIdWorker IdWorker; - } -} - -#endif // _JW_CORE_ID_WORKER_H_ +#ifndef _JW_CORE_ID_WORKER_H_ +#define _JW_CORE_ID_WORKER_H_ + +#include +#include +#include +#include +#include +#include "Noncopyable.h" +#include "Singleton.h" + +// 如果不使用 mutex, 则开启下面这个定义, 但是我发现, 还是开启 mutex 功能, 速度比较快 +// #define SNOWFLAKE_ID_WORKER_NO_LOCK + +namespace Jiawa { + + /** + * @brief 核心 + * 核心功能 + */ + namespace Core { + + /** + * @brief 分布式id生成类 + * https://segmentfault.com/a/1190000011282426 + * https://github.com/twitter/snowflake/blob/snowflake-2010/src/main/scala/com/twitter/service/snowflake/IdWorker.scala + * + * 64bit id: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + * || || || | | | + * |└---------------------------时间戳--------------------------┘└中心-┘└机器-┘ └----序列号----┘ + * | + * 不用 + * SnowFlake的优点: 整体上按照时间自增排序, 并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分), 并且效率较高, 经测试, SnowFlake每秒能够产生26万ID左右. + */ + class SnowflakeIdWorker : private Noncopyable { + + // 实现单例 + friend class Singleton; + + public: + typedef unsigned int UInt; + typedef unsigned long long int UInt64; + +#ifdef SNOWFLAKE_ID_WORKER_NO_LOCK + typedef std::atomic AtomicUInt; + typedef std::atomic AtomicUInt64; +#else + typedef UInt AtomicUInt; + typedef UInt64 AtomicUInt64; +#endif + + void setWorkerId(UInt workerId) { + this->workerId = workerId; + } + + void setDatacenterId(UInt datacenterId) { + this->datacenterId = datacenterId; + } + + UInt64 getId() { + return nextId(); + } + + /** + * 获得下一个ID (该方法是线程安全的) + * + * @return SnowflakeId + */ + UInt64 nextId() { +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + std::unique_lock lock{ mutex }; + AtomicUInt64 timestamp{ 0 }; +#else + static AtomicUInt64 timestamp{ 0 }; +#endif + timestamp = timeGen(); + + // 如果当前时间小于上一次ID生成的时间戳, 说明系统时钟回退过这个时候应当抛出异常 + if (timestamp < lastTimestamp) { + std::ostringstream s; + s << "clock moved backwards. Refusing to generate id for " << lastTimestamp - timestamp << " milliseconds"; + throw std::exception(std::runtime_error(s.str())); + } + + if (lastTimestamp == timestamp) { + // 如果是同一时间生成的, 则进行毫秒内序列 + sequence = (sequence + 1) & sequenceMask; + if (0 == sequence) { + // 毫秒内序列溢出, 阻塞到下一个毫秒,获得新的时间戳 + timestamp = tilNextMillis(lastTimestamp); + } + } else { + sequence = 0; + } + +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + lastTimestamp = timestamp; +#else + lastTimestamp = timestamp.load(); +#endif + + // 移位并通过或运算拼到一起组成64位的ID + return ((timestamp - twepoch) << timestampLeftShift) + | (datacenterId << datacenterIdShift) + | (workerId << workerIdShift) + | sequence; + } + + protected: + SnowflakeIdWorker() : workerId(0), datacenterId(0), sequence(0), lastTimestamp(0) { } + + /** + * 返回以毫秒为单位的当前时间 + * + * @return 当前时间(毫秒) + */ + UInt64 timeGen() const { + auto t = std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()); + return t.time_since_epoch().count(); + } + + /** + * 阻塞到下一个毫秒, 直到获得新的时间戳 + * + * @param lastTimestamp 上次生成ID的时间截 + * @return 当前时间戳 + */ + UInt64 tilNextMillis(UInt64 lastTimestamp) const { + UInt64 timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + private: + +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + std::mutex mutex; +#endif + + /** + * 开始时间截 (2018-01-01 00:00:00.000) + */ + const UInt64 twepoch = 1514736000000; + + /** + * 机器id所占的位数 + */ + const UInt workerIdBits = 5; + + /** + * 数据中心id所占的位数 + */ + const UInt datacenterIdBits = 5; + + /** + * 序列所占的位数 + */ + const UInt sequenceBits = 12; + + /** + * 机器ID向左移12位 + */ + const UInt workerIdShift = sequenceBits; + + /** + * 数据标识id向左移17位 + */ + const UInt datacenterIdShift = workerIdShift + workerIdBits; + + /** + * 时间截向左移22位 + */ + const UInt timestampLeftShift = datacenterIdShift + datacenterIdBits; + + /** + * 支持的最大机器id, 结果是31 + */ + const UInt maxWorkerId = -1 ^ (-1 << workerIdBits); + + /** + * 支持的最大数据中心id, 结果是31 + */ + const UInt maxDatacenterId = -1 ^ (-1 << datacenterIdBits); + + /** + * 生成序列的掩码, 这里为4095 + */ + const UInt sequenceMask = -1 ^ (-1 << sequenceBits); + + /** + * 工作机器id(0~31) + */ + UInt workerId; + + /** + * 数据中心id(0~31) + */ + UInt datacenterId; + + /** + * 毫秒内序列(0~4095) + */ + AtomicUInt sequence{ 0 }; + + /** + * 上次生成ID的时间截 + */ + AtomicUInt64 lastTimestamp{ 0 }; + + }; + + typedef SnowflakeIdWorker IdWorker; + } +} + +#endif // _JW_CORE_ID_WORKER_H_ diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/device/IrisCameraCapEventHandler.h b/device/IrisCameraCapEventHandler.h index 8b976c5..94f5594 100644 --- a/device/IrisCameraCapEventHandler.h +++ b/device/IrisCameraCapEventHandler.h @@ -1,10 +1,9 @@ -#ifndef IRISCAMERACAPEVENTHANDLER_H +#ifndef IRISCAMERACAPEVENTHANDLER_H #define IRISCAMERACAPEVENTHANDLER_H #include #include -#include "include/opencv2/opencv.hpp" -#include "include/daheng/GalaxyIncludes.h" +#include #include "casic/iris/CasicIrisInterface.h" #include "ProMemory.h" diff --git a/device/IrisCameraController.cpp b/device/IrisCameraController.cpp index 0928176..4eea013 100644 --- a/device/IrisCameraController.cpp +++ b/device/IrisCameraController.cpp @@ -1,8 +1,8 @@ -#include "IrisCameraController.h" +#include "IrisCameraController.h" IrisCameraController::IrisCameraController(QObject *parent) : QObject(parent) { - this->irisCamHandler = new IrisCameraCapEventHandler(this); + initIrisCameraController(); } IrisCameraController::~IrisCameraController() { @@ -10,101 +10,204 @@ } -void IrisCameraController::initIrisCamera() +void IrisCameraController::initIrisCameraController() { - IGXFactory::GetInstance().Init(); + // Init GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXInitLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraInitError(); + LOG_ERROR("[CameraController]初始化虹膜相机失败"); + return ; + } + LOG_INFO("[CameraController]初始化虹膜相机成功"); //枚举设备 - IGXFactory::GetInstance().UpdateDeviceList(1000, irisCamList); - - this->OpenDevice(); + UpdateDeviceList(); } void IrisCameraController::openIrisCamera() { - //设置Buffer处理模式 - irisStreamFeaturePtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst"); + GX_STATUS emStatus = GX_STATUS_SUCCESS; - //注册回调函数 - irisStreamPtr->RegisterCaptureCallback(irisCamHandler, &irisCamPtr); + if (m_ui32DeviceNum > 0) { + emStatus = GXOpenDeviceByIndex(1, &m_hDevice); - //开启流层通道 - irisStreamPtr->StartGrab(); + if (emStatus == GX_STATUS_SUCCESS) { + LOG_INFO("[CameraController]开启虹膜相机成功"); - //发送开采命令 - irisFeaturePtr->GetCommandFeature("AcquisitionStart")->Execute(); + // isOpen flag set true + m_bOpen = true; - // 启动定时器 - TimeCounterUtil::getInstance().irisCapCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); // 50ms执行一次定时器 + SetUpAcquisitionThread(); + } + } + + return; } void IrisCameraController::closeIrisCamera() { - + // Release GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXCloseLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraTermError(); + } } void IrisCameraController::startCapture() { // 获取定时器, 绑定定时函数 - connect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString()); + bool bSetDone = false; + // Set acquisition buffer number + bSetDone = SetAcquisitionBufferNum(); + if (!bSetDone) + { + return; + } + + bool bPrepareDone = false; + // Alloc resource for image acquisition + bPrepareDone = m_pobjAcqThread->PrepareForShowImg(); + if (!bPrepareDone) + { + return; + } + + // Device start acquisition and start acquisition thread + StartAcquisition(); + + LOG_DEBUG(QString("[CameraController][startCapture]虹膜相机拍图").toStdString()); + + // Do not start timer when acquisition start failed + if (!m_bAcquisitionStart) + { + return; + } } void IrisCameraController::stopCapture() { - // 获取定时器, 绑定定时函数 - disconnect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString()); - + this->StopAcquisition(); } -void IrisCameraController::getOneFaceFrm() +void IrisCameraController::SetUpAcquisitionThread() { - // 发送软触发命令(在触发模式开启时有效) - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::getLeftAndRightEyeFrame() -{ - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::OpenDevice() -{ - auto device = irisCamList.at(0); - - irisCamPtr = IGXFactory::GetInstance().OpenDeviceByUserID(device.GetUserID(), GX_ACCESS_EXCLUSIVE); - irisFeaturePtr = irisCamPtr->GetRemoteFeatureControl(); - - // 判断设备流是否大于零, 如果大于零则打开流 - int nStreamCount = irisCamPtr->GetStreamCount(); - if (nStreamCount > 0) + // if Acquisition thread is on Stop acquisition thread + if (m_pobjAcqThread != NULL) { - irisStreamPtr = irisCamPtr->OpenStream(0); - irisStreamFeaturePtr = irisStreamPtr->GetFeatureControl(); + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Release acquisition thread object + RELEASE_ALLOC_MEM(m_pobjAcqThread); } - // 建议用户在打开网络相机之后, 根据当前网络环境设置相机的流通道包长值, - // 以提高网络相机的采集性能, 设置方法参考以下代码。 - GX_DEVICE_CLASS_LIST objDeviceClass = irisCamPtr->GetDeviceInfo().GetDeviceClass(); - if(GX_DEVICE_CLASS_GEV == objDeviceClass) + // Instantiation acquisition thread + try { - // 判断设备是否支持流通道数据包功能 - if(true == irisFeaturePtr->IsImplemented("GevSCPSPacketSize")) - { - // 获取当前网络环境的最优包长值 - int nPacketSize = irisStreamPtr->GetOptimalPacketSize(); - // 将最优包长值设置为当前设备的流通道包长值 - irisFeaturePtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize); - } + m_pobjAcqThread = new CAcquisitionThread(); + m_pobjAcqThread->m_hDevice = m_hDevice; + } + catch (std::bad_alloc &e) + { + QMessageBox::about(NULL, "Allocate memory error", "Cannot allocate memory, please exit this app!"); + RELEASE_ALLOC_MEM(m_pobjAcqThread); + return; } - //设置采集模式为连续采集模式 - irisFeaturePtr->GetEnumFeature("AcquisitionMode")->SetValue("Continuous"); + return; +} - //设置触发模式关 - irisFeaturePtr->GetEnumFeature("TriggerMode")->SetValue("On"); - irisFeaturePtr->GetEnumFeature("TriggerSource")->SetValue("Software"); +void IrisCameraController::UpdateDeviceList() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Enumerate Devcie List + emStatus = GXUpdateDeviceList(&m_ui32DeviceNum, ENUMRATE_TIME_OUT); + + LOG_INFO(QString("[CameraController]枚举虹膜相机成功[%1]").arg(m_ui32DeviceNum).toStdString()); + + return; +} + +void IrisCameraController::StartAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + emStatus = GXStreamOn(m_hDevice); + + // Set acquisition thread run flag + m_pobjAcqThread->m_bAcquisitionThreadFlag = true; + + // Acquisition thread start + m_pobjAcqThread->start(); + + // isStart flag set true + m_bAcquisitionStart = true; + + return; +} + +void IrisCameraController::StopAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Turn off stream + emStatus = GXStreamOff(m_hDevice); + + // isStart flag set false + m_bAcquisitionStart = false; + + return; +} + +bool IrisCameraController::SetAcquisitionBufferNum() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + uint64_t ui64BufferNum = 0; + int64_t i64PayloadSize = 0; + + // Get device current payload size + emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &i64PayloadSize); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Set buffer quantity of acquisition queue + if (i64PayloadSize == 0) + { + return false; + } + + // Calculate a reasonable number of Buffers for different payload size + // Small ROI and high frame rate will requires more acquisition Buffer + const size_t MAX_MEMORY_SIZE = 8 * 1024 * 1024; // The maximum number of memory bytes available for allocating frame Buffer + const size_t MIN_BUFFER_NUM = 5; // Minimum frame Buffer number + const size_t MAX_BUFFER_NUM = 450; // Maximum frame Buffer number + ui64BufferNum = MAX_MEMORY_SIZE / i64PayloadSize; + ui64BufferNum = (ui64BufferNum <= MIN_BUFFER_NUM) ? MIN_BUFFER_NUM : ui64BufferNum; + ui64BufferNum = (ui64BufferNum >= MAX_BUFFER_NUM) ? MAX_BUFFER_NUM : ui64BufferNum; + + emStatus = GXSetAcqusitionBufferNumber(m_hDevice, ui64BufferNum); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Transfer buffer number to acquisition thread class for using GXDQAllBufs + m_pobjAcqThread->m_ui64AcquisitionBufferNum = ui64BufferNum; + + return true; } diff --git a/device/IrisCameraController.h b/device/IrisCameraController.h index 5d7e269..67cbe2f 100644 --- a/device/IrisCameraController.h +++ b/device/IrisCameraController.h @@ -1,11 +1,12 @@ -#ifndef IRISCAMERACONTROLLER_H +#ifndef IRISCAMERACONTROLLER_H #define IRISCAMERACONTROLLER_H #include -#include "IrisCameraCapEventHandler.h" +#include "AcquisitionThread.h" +#include "utils/UtilInclude.h" -class IrisCameraCapEventHandler; +#define ENUMRATE_TIME_OUT 200 class IrisCameraController : public QObject { @@ -14,36 +15,31 @@ explicit IrisCameraController(QObject *parent = nullptr); ~IrisCameraController(); - // 初始化并打开人脸相机 - void initIrisCamera(); void openIrisCamera(); void closeIrisCamera(); void startCapture(); void stopCapture(); - void getLeftAndRightEyeFrame(); + CAcquisitionThread * m_pobjAcqThread; + GX_DEV_HANDLE m_hDevice; ///< Device Handle + uint32_t m_ui32DeviceNum; ///< Device number enumerated - IrisCameraCapEventHandler * irisCamHandler; + bool m_bOpen; ///< Flag : camera is opened or not + bool m_bAcquisitionStart; ///< Flag : camera is acquiring or not private: - GxIAPICPP::gxdeviceinfo_vector irisCamList; - - CGXDevicePointer irisCamPtr; ///< 设备句柄 - - CGXStreamPointer irisStreamPtr; ///< 左眼设备流 - - CGXFeatureControlPointer irisFeaturePtr; ///< 左眼属性控制器 - - CGXFeatureControlPointer irisStreamFeaturePtr; ///< 左眼流层控制器对象 - - void OpenDevice(); + // 初始化并打开人脸相机 + void initIrisCameraController(); + void SetUpAcquisitionThread(); + void UpdateDeviceList(); + bool SetAcquisitionBufferNum(); + void StartAcquisition(); + void StopAcquisition(); signals: - -public slots: - void getOneFaceFrm(); - + void irisCameraInitError(); + void irisCameraTermError(); }; #endif // IRISCAMERACONTROLLER_H diff --git a/device/device.pri b/device/device.pri index d1330a0..583721b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,13 +1,14 @@ HEADERS += $$PWD/IrisCameraController.h -HEADERS += $$PWD/IrisCameraCapEventHandler.h -#HEADERS += $$PWD/iris/IrisRegistProcess.h +#HEADERS += $$PWD/IrisCameraCapEventHandler.h +HEADERS += $$PWD/Common.h +HEADERS += $$PWD/AcquisitionThread.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h SOURCES += $$PWD/IrisCameraController.cpp -SOURCES += $$PWD/IrisCameraCapEventHandler.cpp -#SOURCES += $$PWD/iris/IrisRegistProcess.cpp +#SOURCES += $$PWD/IrisCameraCapEventHandler.cpp +SOURCES += $$PWD/AcquisitionThread.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 38f54fe..e4c8a02 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -11,7 +11,7 @@ // 连接算法服务 clientUtil = new SocketClientUtil(this); - clientUtil->connect("192.168.83.223", 50007); + clientUtil->connect(SettingConfig::getInstance().DEBUG_SEGMENT_IP, 50007); // 调用socket发送消息 connect(this, &IrisRecogProcess::sendDataToExract, clientUtil, &SocketClientUtil::sendData); @@ -43,18 +43,18 @@ continue; } - // 1. 图像栈中没有图像则直接返回 - if (ProMemory::getInstance().isIrisQueueEmpty() == true) + // 1. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 + if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) { - qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); + qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } - // 2. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 - if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) + // 2. 图像栈中没有图像则直接返回 + if (ProMemory::getInstance().isIrisQueueEmpty() == true) { - qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); + qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } @@ -73,7 +73,7 @@ int findEyeLast = timer.elapsed(); qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); -// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.matData = cv::imread("/home/casic/code/irisLogs/145333.552.bmp", 0); // irisInfo.hasEye = true; // 4.1 没有找到眼睛则返回 @@ -117,11 +117,10 @@ // 缩放到320 * 240 cv::resize(segMat, segMat, cv::Size(SettingConfig::getInstance().IRIS_WIDTH * 0.5, SettingConfig::getInstance().IRIS_HEIGHT * 0.5)); - - // std::string filename = QString("%1\\%2\\%3-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - // cv::imwrite(filename, segMat); - // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - +/* + std::string filename = QString("%1/%2/%3-seg.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(filename, segMat); +*/ int segMatSize = segMat.cols * segMat.rows; QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 @@ -167,9 +166,9 @@ // 成功接收后清除缓存区 clientUtil->resetRecvBuffer(); /* - std::string pupilSeg = QString("%1\\%2\\%3-pupil-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string maskSeg = QString("%1\\%2\\%3-mask-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string irisSeg = QString("%1\\%2\\%3-iris-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string pupilSeg = QString("%1/%2/%3-pupil-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); cv::imwrite(pupilSeg, pupil); cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); @@ -196,12 +195,20 @@ CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; irisInfo = casic::iris::CasicIrisInterface::getInstance().irisEncode(irisInfo); /* - std::string codeFilename = QString("%1\\%2\\%3-code.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string codeFilename = QString("%1/%2/%3-code.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string maskFilename = QString("%1/%2/%3-mask.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); */ + if (irisInfo.postProcSucc == false) { + qDebug() << "算法post process失败,暂停200ms"; + + addOneTryCount(); + this->msleep(THREAD_MSLEEP); // 200ms后再判断 + continue; + } + // 从编码中提取特征值 irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); @@ -211,6 +218,8 @@ CasicIrisRecState::getInstance().extractTmLast = encodeLast; CasicIrisRecState::getInstance().recogTimeLast += encodeLast; +// cv::imwrite(QString("%1/%2/%3.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(), irisInfo.matData); + // 开始匹配 timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) @@ -219,7 +228,7 @@ float score = casic::iris::CasicIrisInterface::getInstance().calculatePairPoints(feature.irisFeatureCode, irisInfo.irisFeatureCode); // 计算压缩编码的比较值 -// cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); +// cv::imwrite(QString("%1/%2/%3-%4.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; @@ -251,7 +260,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } @@ -268,7 +277,7 @@ CasicIrisRecState::getInstance().tryCount = 0; this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); emit failedMatchedIris(); @@ -290,7 +299,7 @@ // 识别失败时暂停工作 待返回识别界面时再开始工作和拍图 this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); } } else if (ProMemory::getInstance().appState == AppConstants::ApplicationState::STATE_WORKING) @@ -298,7 +307,8 @@ CasicIrisRecState::getInstance().noEyeCount++; // 如果在工作状态 则超过一定次数后返回待机 - if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT) + if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT && + SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT > 0) { // 发送信号待机 emit backToLockScreen(); diff --git a/device/iris/IrisRecogProcess.h b/device/iris/IrisRecogProcess.h index 9a3eec6..e21c1a7 100644 --- a/device/iris/IrisRecogProcess.h +++ b/device/iris/IrisRecogProcess.h @@ -1,4 +1,4 @@ -#ifndef IRISRECOGPROCESS_H +#ifndef IRISRECOGPROCESS_H #define IRISRECOGPROCESS_H #define THREAD_MSLEEP 200 @@ -10,6 +10,7 @@ #include "ProMemory.h" #include "device/iris/CasicIrisRecState.h" +#include "casic/iris/CasicIrisInterface.h" class IrisRecogProcess : public QThread { diff --git a/main.cpp b/main.cpp index 9052ddb..3bfb1c6 100644 --- a/main.cpp +++ b/main.cpp @@ -1,11 +1,11 @@ -#include "MainWindowForm.h" - -#include - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - MainWindowForm w; - w.show(); - return a.exec(); -} +#include "MainWindowForm.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindowForm w; + w.show(); + return a.exec(); +} diff --git a/utils/ImageUtil.cpp b/utils/ImageUtil.cpp index ff77331..d40ea79 100644 --- a/utils/ImageUtil.cpp +++ b/utils/ImageUtil.cpp @@ -1,107 +1,107 @@ -#include "ImageUtil.h" - -ImageUtil::ImageUtil() -{ - -} - -QImage ImageUtil::MatImageToQImage(const cv::Mat &src) -{ - //CV_8UC1 8位无符号的单通道---灰度图片 - if(src.type() == CV_8UC1) - { - QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); - return qImage; - } - //为3通道的彩色图片 - else if(src.type() == CV_8UC3) - { - //得到图像的的首地址 - const uchar *pSrc = (const uchar*)src.data; - //以src构造图片 - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); - } - //四通道图片, 带Alpha通道的RGB彩色图像 - else if(src.type() == CV_8UC4) - { - const uchar *pSrc = (const uchar*)src.data; - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); - //返回图像的子区域作为一个新图像 - return qImage.copy(); - } - else - { - return QImage(); - } -} - -cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) -{ - cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); - return img; -} - -cv::Mat ImageUtil::QImageToMat(QImage image) -{ - cv::Mat mat; - switch(image.format()) - { - case QImage::Format_ARGB32: - case QImage::Format_RGB32: - case QImage::Format_ARGB32_Premultiplied: - mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_RGB888: - mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); - cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); - break; - case QImage::Format_Indexed8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_Grayscale8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); - break; - - default: - break; - } - - mat = mat.clone(); - - return mat; -} - -/* -QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) -{ - QImage qImage(data, width, height, format); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); -} - -QString ImageUtil::QImageToBase64(QImage image) -{ - QByteArray ba; - QBuffer buf(&ba); - image.save(&buf, "bmp"); - QString base64String = ba.toBase64(); - return base64String; -} - -cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) -{ - cv::Mat matClone = src.clone(); - cv::Rect bigRect; - - bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; - bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; - bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; - bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; - - cv::Mat roi = matClone(bigRect); - - return roi; -} -*/ +#include "ImageUtil.h" + +ImageUtil::ImageUtil() +{ + +} + +QImage ImageUtil::MatImageToQImage(const cv::Mat &src) +{ + //CV_8UC1 8位无符号的单通道---灰度图片 + if(src.type() == CV_8UC1) + { + QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); + return qImage; + } + //为3通道的彩色图片 + else if(src.type() == CV_8UC3) + { + //得到图像的的首地址 + const uchar *pSrc = (const uchar*)src.data; + //以src构造图片 + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); + } + //四通道图片, 带Alpha通道的RGB彩色图像 + else if(src.type() == CV_8UC4) + { + const uchar *pSrc = (const uchar*)src.data; + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); + //返回图像的子区域作为一个新图像 + return qImage.copy(); + } + else + { + return QImage(); + } +} + +cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) +{ + cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); + return img; +} + +cv::Mat ImageUtil::QImageToMat(QImage image) +{ + cv::Mat mat; + switch(image.format()) + { + case QImage::Format_ARGB32: + case QImage::Format_RGB32: + case QImage::Format_ARGB32_Premultiplied: + mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_RGB888: + mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); + cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); + break; + case QImage::Format_Indexed8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_Grayscale8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); + break; + + default: + break; + } + + mat = mat.clone(); + + return mat; +} + +/* +QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) +{ + QImage qImage(data, width, height, format); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); +} + +QString ImageUtil::QImageToBase64(QImage image) +{ + QByteArray ba; + QBuffer buf(&ba); + image.save(&buf, "bmp"); + QString base64String = ba.toBase64(); + return base64String; +} + +cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) +{ + cv::Mat matClone = src.clone(); + cv::Rect bigRect; + + bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; + bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; + bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; + bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; + + cv::Mat roi = matClone(bigRect); + + return roi; +} +*/ diff --git a/utils/ImageUtil.h b/utils/ImageUtil.h index d9bf00a..4b702f4 100644 --- a/utils/ImageUtil.h +++ b/utils/ImageUtil.h @@ -1,23 +1,23 @@ -#ifndef IMAGEUTIL_H -#define IMAGEUTIL_H - -#include -#include -#include "opencv2/opencv.hpp" - -class ImageUtil -{ -public: - ImageUtil(); - - static QImage MatImageToQImage(const cv::Mat &src); -// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); - - static cv::Mat ucharToMat(unsigned char * data, int row, int col); - static cv::Mat QImageToMat(QImage image); -// static QString QImageToBase64(QImage image); - -// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); -}; - -#endif // IMAGEUTIL_H +#ifndef IMAGEUTIL_H +#define IMAGEUTIL_H + +#include +#include +#include "opencv2/opencv.hpp" + +class ImageUtil +{ +public: + ImageUtil(); + + static QImage MatImageToQImage(const cv::Mat &src); +// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); + + static cv::Mat ucharToMat(unsigned char * data, int row, int col); + static cv::Mat QImageToMat(QImage image); +// static QString QImageToBase64(QImage image); + +// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); +}; + +#endif // IMAGEUTIL_H diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp index 663db0f..05c4c68 100644 --- a/utils/SettingConfig.cpp +++ b/utils/SettingConfig.cpp @@ -1,4 +1,4 @@ -#include "SettingConfig.h" +#include "SettingConfig.h" #include SettingConfig::SettingConfig() @@ -34,6 +34,9 @@ LOG_FILE = getProperty("log", "logFile").toString(); LOG_LEVEL = getProperty("log", "logLevel").toString(); + + DEBUG_CAMERA_ROTATE = getProperty("debug", "cameraRotate").toString(); + DEBUG_SEGMENT_IP = getProperty("debug", "segmentIp").toString(); } diff --git a/utils/SettingConfig.h b/utils/SettingConfig.h index b65f553..c35d6ab 100644 --- a/utils/SettingConfig.h +++ b/utils/SettingConfig.h @@ -1,4 +1,4 @@ -#ifndef SETTINGCONFIG_H +#ifndef SETTINGCONFIG_H #define SETTINGCONFIG_H #include @@ -55,6 +55,9 @@ QString LOG_FILE; QString LOG_LEVEL; + QString DEBUG_CAMERA_ROTATE; + QString DEBUG_SEGMENT_IP; + private: SettingConfig(); diff --git a/utils/SocketClientUtil.cpp b/utils/SocketClientUtil.cpp index d539d64..20b8869 100644 --- a/utils/SocketClientUtil.cpp +++ b/utils/SocketClientUtil.cpp @@ -1,9 +1,10 @@ -#include "SocketClientUtil.h" +#include "SocketClientUtil.h" #include "utils/ByteUtil.h" SocketClientUtil::SocketClientUtil(QObject *parent) : QObject(parent) { QObject::connect(&objClient, &QTcpSocket::readyRead, this, &SocketClientUtil::readData); + QObject::connect(&objClient, &QTcpSocket::disconnected, this, &SocketClientUtil::socketReconnect); } void SocketClientUtil::connect(QString host, int port) @@ -16,6 +17,10 @@ void SocketClientUtil::closeConnect() { + QObject::disconnect(&objClient, &QTcpSocket::readyRead, this, &SocketClientUtil::readData); + QObject::disconnect(&objClient, &QTcpSocket::disconnected, this, &SocketClientUtil::socketReconnect); + + objClient.disconnectFromHost(); objClient.close(); } @@ -45,3 +50,9 @@ emit this->responseReaded(); } } + +void SocketClientUtil::socketReconnect() +{ + objClient.close(); + objClient.connectToHost(this->host, this->port); +} diff --git a/utils/SocketClientUtil.h b/utils/SocketClientUtil.h index 96b60e0..8bd1b8c 100644 --- a/utils/SocketClientUtil.h +++ b/utils/SocketClientUtil.h @@ -1,4 +1,4 @@ -#ifndef SOCKETCLIENTUTIL_H +#ifndef SOCKETCLIENTUTIL_H #define SOCKETCLIENTUTIL_H #include @@ -30,6 +30,7 @@ public slots: void readData(); void sendData(QByteArray data); + void socketReconnect(); }; diff --git a/utils/TimeCounterUtil.cpp b/utils/TimeCounterUtil.cpp index 275945f..78c3d69 100644 --- a/utils/TimeCounterUtil.cpp +++ b/utils/TimeCounterUtil.cpp @@ -1,8 +1,9 @@ -#include "TimeCounterUtil.h" - -TimeCounterUtil::TimeCounterUtil() -{ - faceCapCounter = new QTimer(); - irisCapCounter = new QTimer(); - clockCounter = new QTimer(); -} +#include "TimeCounterUtil.h" + +TimeCounterUtil::TimeCounterUtil() +{ + faceCapCounter = new QTimer(); + irisCapCounter = new QTimer(); + clockCounter = new QTimer(); + videoCounter = new QTimer(); +} diff --git a/utils/TimeCounterUtil.h b/utils/TimeCounterUtil.h index 28b29f1..91f8da0 100644 --- a/utils/TimeCounterUtil.h +++ b/utils/TimeCounterUtil.h @@ -1,29 +1,30 @@ -#ifndef TIMECOUNTERUTIL_H -#define TIMECOUNTERUTIL_H - -#include -#include - -class TimeCounterUtil : public QObject -{ -public: - - ~TimeCounterUtil() {}; - TimeCounterUtil(const TimeCounterUtil&)=delete; - TimeCounterUtil& operator=(const TimeCounterUtil&)=delete; - - static TimeCounterUtil& getInstance() { - static TimeCounterUtil instance; - return instance; - } - - QTimer * faceCapCounter; - QTimer * irisCapCounter; - QTimer * clockCounter; - -private: - TimeCounterUtil(); - -}; - -#endif // TIMECOUNTERUTIL_H +#ifndef TIMECOUNTERUTIL_H +#define TIMECOUNTERUTIL_H + +#include +#include + +class TimeCounterUtil : public QObject +{ +public: + + ~TimeCounterUtil() {}; + TimeCounterUtil(const TimeCounterUtil&)=delete; + TimeCounterUtil& operator=(const TimeCounterUtil&)=delete; + + static TimeCounterUtil& getInstance() { + static TimeCounterUtil instance; + return instance; + } + + QTimer * faceCapCounter; + QTimer * irisCapCounter; + QTimer * clockCounter; + QTimer * videoCounter; // show video images on main window + +private: + TimeCounterUtil(); + +}; + +#endif // TIMECOUNTERUTIL_H diff --git a/utils/UtilInclude.h b/utils/UtilInclude.h index 0b329c9..bea17be 100644 --- a/utils/UtilInclude.h +++ b/utils/UtilInclude.h @@ -1,15 +1,15 @@ -#ifndef UTILINCLUDE_H -#define UTILINCLUDE_H - -#include -#include "ByteUtil.h" -#include "ImageUtil.h" -#include "LogUtil.h" -#include "SettingConfig.h" -#include "SocketClientUtil.h" -#include "SpeakerUtil.h" -#include "TimeCounterUtil.h" -//#include "UDPClientUtil.h" -//#include "HttpRequestUtil.h" - -#endif // UTILINCLUDE_H +#ifndef UTILINCLUDE_H +#define UTILINCLUDE_H + +#include +#include "ByteUtil.h" +#include "ImageUtil.h" +#include "LogUtil.h" +#include "SettingConfig.h" +#include "SocketClientUtil.h" +#include "SpeakerUtil.h" +#include "TimeCounterUtil.h" +//#include "UDPClientUtil.h" +//#include "HttpRequestUtil.h" + +#endif // UTILINCLUDE_H diff --git a/utils/id/IdWorker.h b/utils/id/IdWorker.h index 6c48aa9..079bbcb 100644 --- a/utils/id/IdWorker.h +++ b/utils/id/IdWorker.h @@ -1,218 +1,218 @@ -#ifndef _JW_CORE_ID_WORKER_H_ -#define _JW_CORE_ID_WORKER_H_ - -#include -#include -#include -#include -#include -#include "Noncopyable.h" -#include "Singleton.h" - -// 如果不使用 mutex, 则开启下面这个定义, 但是我发现, 还是开启 mutex 功能, 速度比较快 -// #define SNOWFLAKE_ID_WORKER_NO_LOCK - -namespace Jiawa { - - /** - * @brief 核心 - * 核心功能 - */ - namespace Core { - - /** - * @brief 分布式id生成类 - * https://segmentfault.com/a/1190000011282426 - * https://github.com/twitter/snowflake/blob/snowflake-2010/src/main/scala/com/twitter/service/snowflake/IdWorker.scala - * - * 64bit id: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 - * || || || | | | - * |└---------------------------时间戳--------------------------┘└中心-┘└机器-┘ └----序列号----┘ - * | - * 不用 - * SnowFlake的优点: 整体上按照时间自增排序, 并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分), 并且效率较高, 经测试, SnowFlake每秒能够产生26万ID左右. - */ - class SnowflakeIdWorker : private Noncopyable { - - // 实现单例 - friend class Singleton; - - public: - typedef unsigned int UInt; - typedef unsigned long long int UInt64; - -#ifdef SNOWFLAKE_ID_WORKER_NO_LOCK - typedef std::atomic AtomicUInt; - typedef std::atomic AtomicUInt64; -#else - typedef UInt AtomicUInt; - typedef UInt64 AtomicUInt64; -#endif - - void setWorkerId(UInt workerId) { - this->workerId = workerId; - } - - void setDatacenterId(UInt datacenterId) { - this->datacenterId = datacenterId; - } - - UInt64 getId() { - return nextId(); - } - - /** - * 获得下一个ID (该方法是线程安全的) - * - * @return SnowflakeId - */ - UInt64 nextId() { -#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK - std::unique_lock lock{ mutex }; - AtomicUInt64 timestamp{ 0 }; -#else - static AtomicUInt64 timestamp{ 0 }; -#endif - timestamp = timeGen(); - - // 如果当前时间小于上一次ID生成的时间戳, 说明系统时钟回退过这个时候应当抛出异常 - if (timestamp < lastTimestamp) { - std::ostringstream s; - s << "clock moved backwards. Refusing to generate id for " << lastTimestamp - timestamp << " milliseconds"; - throw std::exception(std::runtime_error(s.str())); - } - - if (lastTimestamp == timestamp) { - // 如果是同一时间生成的, 则进行毫秒内序列 - sequence = (sequence + 1) & sequenceMask; - if (0 == sequence) { - // 毫秒内序列溢出, 阻塞到下一个毫秒,获得新的时间戳 - timestamp = tilNextMillis(lastTimestamp); - } - } else { - sequence = 0; - } - -#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK - lastTimestamp = timestamp; -#else - lastTimestamp = timestamp.load(); -#endif - - // 移位并通过或运算拼到一起组成64位的ID - return ((timestamp - twepoch) << timestampLeftShift) - | (datacenterId << datacenterIdShift) - | (workerId << workerIdShift) - | sequence; - } - - protected: - SnowflakeIdWorker() : workerId(0), datacenterId(0), sequence(0), lastTimestamp(0) { } - - /** - * 返回以毫秒为单位的当前时间 - * - * @return 当前时间(毫秒) - */ - UInt64 timeGen() const { - auto t = std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()); - return t.time_since_epoch().count(); - } - - /** - * 阻塞到下一个毫秒, 直到获得新的时间戳 - * - * @param lastTimestamp 上次生成ID的时间截 - * @return 当前时间戳 - */ - UInt64 tilNextMillis(UInt64 lastTimestamp) const { - UInt64 timestamp = timeGen(); - while (timestamp <= lastTimestamp) { - timestamp = timeGen(); - } - return timestamp; - } - - private: - -#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK - std::mutex mutex; -#endif - - /** - * 开始时间截 (2018-01-01 00:00:00.000) - */ - const UInt64 twepoch = 1514736000000; - - /** - * 机器id所占的位数 - */ - const UInt workerIdBits = 5; - - /** - * 数据中心id所占的位数 - */ - const UInt datacenterIdBits = 5; - - /** - * 序列所占的位数 - */ - const UInt sequenceBits = 12; - - /** - * 机器ID向左移12位 - */ - const UInt workerIdShift = sequenceBits; - - /** - * 数据标识id向左移17位 - */ - const UInt datacenterIdShift = workerIdShift + workerIdBits; - - /** - * 时间截向左移22位 - */ - const UInt timestampLeftShift = datacenterIdShift + datacenterIdBits; - - /** - * 支持的最大机器id, 结果是31 - */ - const UInt maxWorkerId = -1 ^ (-1 << workerIdBits); - - /** - * 支持的最大数据中心id, 结果是31 - */ - const UInt maxDatacenterId = -1 ^ (-1 << datacenterIdBits); - - /** - * 生成序列的掩码, 这里为4095 - */ - const UInt sequenceMask = -1 ^ (-1 << sequenceBits); - - /** - * 工作机器id(0~31) - */ - UInt workerId; - - /** - * 数据中心id(0~31) - */ - UInt datacenterId; - - /** - * 毫秒内序列(0~4095) - */ - AtomicUInt sequence{ 0 }; - - /** - * 上次生成ID的时间截 - */ - AtomicUInt64 lastTimestamp{ 0 }; - - }; - - typedef SnowflakeIdWorker IdWorker; - } -} - -#endif // _JW_CORE_ID_WORKER_H_ +#ifndef _JW_CORE_ID_WORKER_H_ +#define _JW_CORE_ID_WORKER_H_ + +#include +#include +#include +#include +#include +#include "Noncopyable.h" +#include "Singleton.h" + +// 如果不使用 mutex, 则开启下面这个定义, 但是我发现, 还是开启 mutex 功能, 速度比较快 +// #define SNOWFLAKE_ID_WORKER_NO_LOCK + +namespace Jiawa { + + /** + * @brief 核心 + * 核心功能 + */ + namespace Core { + + /** + * @brief 分布式id生成类 + * https://segmentfault.com/a/1190000011282426 + * https://github.com/twitter/snowflake/blob/snowflake-2010/src/main/scala/com/twitter/service/snowflake/IdWorker.scala + * + * 64bit id: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + * || || || | | | + * |└---------------------------时间戳--------------------------┘└中心-┘└机器-┘ └----序列号----┘ + * | + * 不用 + * SnowFlake的优点: 整体上按照时间自增排序, 并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分), 并且效率较高, 经测试, SnowFlake每秒能够产生26万ID左右. + */ + class SnowflakeIdWorker : private Noncopyable { + + // 实现单例 + friend class Singleton; + + public: + typedef unsigned int UInt; + typedef unsigned long long int UInt64; + +#ifdef SNOWFLAKE_ID_WORKER_NO_LOCK + typedef std::atomic AtomicUInt; + typedef std::atomic AtomicUInt64; +#else + typedef UInt AtomicUInt; + typedef UInt64 AtomicUInt64; +#endif + + void setWorkerId(UInt workerId) { + this->workerId = workerId; + } + + void setDatacenterId(UInt datacenterId) { + this->datacenterId = datacenterId; + } + + UInt64 getId() { + return nextId(); + } + + /** + * 获得下一个ID (该方法是线程安全的) + * + * @return SnowflakeId + */ + UInt64 nextId() { +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + std::unique_lock lock{ mutex }; + AtomicUInt64 timestamp{ 0 }; +#else + static AtomicUInt64 timestamp{ 0 }; +#endif + timestamp = timeGen(); + + // 如果当前时间小于上一次ID生成的时间戳, 说明系统时钟回退过这个时候应当抛出异常 + if (timestamp < lastTimestamp) { + std::ostringstream s; + s << "clock moved backwards. Refusing to generate id for " << lastTimestamp - timestamp << " milliseconds"; + throw std::exception(std::runtime_error(s.str())); + } + + if (lastTimestamp == timestamp) { + // 如果是同一时间生成的, 则进行毫秒内序列 + sequence = (sequence + 1) & sequenceMask; + if (0 == sequence) { + // 毫秒内序列溢出, 阻塞到下一个毫秒,获得新的时间戳 + timestamp = tilNextMillis(lastTimestamp); + } + } else { + sequence = 0; + } + +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + lastTimestamp = timestamp; +#else + lastTimestamp = timestamp.load(); +#endif + + // 移位并通过或运算拼到一起组成64位的ID + return ((timestamp - twepoch) << timestampLeftShift) + | (datacenterId << datacenterIdShift) + | (workerId << workerIdShift) + | sequence; + } + + protected: + SnowflakeIdWorker() : workerId(0), datacenterId(0), sequence(0), lastTimestamp(0) { } + + /** + * 返回以毫秒为单位的当前时间 + * + * @return 当前时间(毫秒) + */ + UInt64 timeGen() const { + auto t = std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()); + return t.time_since_epoch().count(); + } + + /** + * 阻塞到下一个毫秒, 直到获得新的时间戳 + * + * @param lastTimestamp 上次生成ID的时间截 + * @return 当前时间戳 + */ + UInt64 tilNextMillis(UInt64 lastTimestamp) const { + UInt64 timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + private: + +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + std::mutex mutex; +#endif + + /** + * 开始时间截 (2018-01-01 00:00:00.000) + */ + const UInt64 twepoch = 1514736000000; + + /** + * 机器id所占的位数 + */ + const UInt workerIdBits = 5; + + /** + * 数据中心id所占的位数 + */ + const UInt datacenterIdBits = 5; + + /** + * 序列所占的位数 + */ + const UInt sequenceBits = 12; + + /** + * 机器ID向左移12位 + */ + const UInt workerIdShift = sequenceBits; + + /** + * 数据标识id向左移17位 + */ + const UInt datacenterIdShift = workerIdShift + workerIdBits; + + /** + * 时间截向左移22位 + */ + const UInt timestampLeftShift = datacenterIdShift + datacenterIdBits; + + /** + * 支持的最大机器id, 结果是31 + */ + const UInt maxWorkerId = -1 ^ (-1 << workerIdBits); + + /** + * 支持的最大数据中心id, 结果是31 + */ + const UInt maxDatacenterId = -1 ^ (-1 << datacenterIdBits); + + /** + * 生成序列的掩码, 这里为4095 + */ + const UInt sequenceMask = -1 ^ (-1 << sequenceBits); + + /** + * 工作机器id(0~31) + */ + UInt workerId; + + /** + * 数据中心id(0~31) + */ + UInt datacenterId; + + /** + * 毫秒内序列(0~4095) + */ + AtomicUInt sequence{ 0 }; + + /** + * 上次生成ID的时间截 + */ + AtomicUInt64 lastTimestamp{ 0 }; + + }; + + typedef SnowflakeIdWorker IdWorker; + } +} + +#endif // _JW_CORE_ID_WORKER_H_ diff --git a/utils/id/Noncopyable.h b/utils/id/Noncopyable.h index d87f58a..4fc555a 100644 --- a/utils/id/Noncopyable.h +++ b/utils/id/Noncopyable.h @@ -1,31 +1,31 @@ -#ifndef _JW_CORE_NONCOPYABLE_H_ -#define _JW_CORE_NONCOPYABLE_H_ - - -// Private copy constructor and copy assignment ensure classes derived from -// class noncopyable cannot be copied. - -namespace Jiawa { - namespace Core { - - // protection from unintended ADL(Argument Dependent Lookup) - namespace Noncopyable_ { - - class Noncopyable - { - protected: - Noncopyable() = default; - ~Noncopyable() = default; - - Noncopyable(const Noncopyable&) = delete; - Noncopyable(const Noncopyable&&) = delete; - Noncopyable& operator=(const Noncopyable&) = delete; - Noncopyable& operator=(const Noncopyable&&) = delete; - }; - } - - typedef Noncopyable_::Noncopyable Noncopyable; - } -} - -#endif // _JW_CORE_NONCOPYABLE_H_ +#ifndef _JW_CORE_NONCOPYABLE_H_ +#define _JW_CORE_NONCOPYABLE_H_ + + +// Private copy constructor and copy assignment ensure classes derived from +// class noncopyable cannot be copied. + +namespace Jiawa { + namespace Core { + + // protection from unintended ADL(Argument Dependent Lookup) + namespace Noncopyable_ { + + class Noncopyable + { + protected: + Noncopyable() = default; + ~Noncopyable() = default; + + Noncopyable(const Noncopyable&) = delete; + Noncopyable(const Noncopyable&&) = delete; + Noncopyable& operator=(const Noncopyable&) = delete; + Noncopyable& operator=(const Noncopyable&&) = delete; + }; + } + + typedef Noncopyable_::Noncopyable Noncopyable; + } +} + +#endif // _JW_CORE_NONCOPYABLE_H_ diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/device/IrisCameraCapEventHandler.h b/device/IrisCameraCapEventHandler.h index 8b976c5..94f5594 100644 --- a/device/IrisCameraCapEventHandler.h +++ b/device/IrisCameraCapEventHandler.h @@ -1,10 +1,9 @@ -#ifndef IRISCAMERACAPEVENTHANDLER_H +#ifndef IRISCAMERACAPEVENTHANDLER_H #define IRISCAMERACAPEVENTHANDLER_H #include #include -#include "include/opencv2/opencv.hpp" -#include "include/daheng/GalaxyIncludes.h" +#include #include "casic/iris/CasicIrisInterface.h" #include "ProMemory.h" diff --git a/device/IrisCameraController.cpp b/device/IrisCameraController.cpp index 0928176..4eea013 100644 --- a/device/IrisCameraController.cpp +++ b/device/IrisCameraController.cpp @@ -1,8 +1,8 @@ -#include "IrisCameraController.h" +#include "IrisCameraController.h" IrisCameraController::IrisCameraController(QObject *parent) : QObject(parent) { - this->irisCamHandler = new IrisCameraCapEventHandler(this); + initIrisCameraController(); } IrisCameraController::~IrisCameraController() { @@ -10,101 +10,204 @@ } -void IrisCameraController::initIrisCamera() +void IrisCameraController::initIrisCameraController() { - IGXFactory::GetInstance().Init(); + // Init GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXInitLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraInitError(); + LOG_ERROR("[CameraController]初始化虹膜相机失败"); + return ; + } + LOG_INFO("[CameraController]初始化虹膜相机成功"); //枚举设备 - IGXFactory::GetInstance().UpdateDeviceList(1000, irisCamList); - - this->OpenDevice(); + UpdateDeviceList(); } void IrisCameraController::openIrisCamera() { - //设置Buffer处理模式 - irisStreamFeaturePtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst"); + GX_STATUS emStatus = GX_STATUS_SUCCESS; - //注册回调函数 - irisStreamPtr->RegisterCaptureCallback(irisCamHandler, &irisCamPtr); + if (m_ui32DeviceNum > 0) { + emStatus = GXOpenDeviceByIndex(1, &m_hDevice); - //开启流层通道 - irisStreamPtr->StartGrab(); + if (emStatus == GX_STATUS_SUCCESS) { + LOG_INFO("[CameraController]开启虹膜相机成功"); - //发送开采命令 - irisFeaturePtr->GetCommandFeature("AcquisitionStart")->Execute(); + // isOpen flag set true + m_bOpen = true; - // 启动定时器 - TimeCounterUtil::getInstance().irisCapCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); // 50ms执行一次定时器 + SetUpAcquisitionThread(); + } + } + + return; } void IrisCameraController::closeIrisCamera() { - + // Release GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXCloseLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraTermError(); + } } void IrisCameraController::startCapture() { // 获取定时器, 绑定定时函数 - connect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString()); + bool bSetDone = false; + // Set acquisition buffer number + bSetDone = SetAcquisitionBufferNum(); + if (!bSetDone) + { + return; + } + + bool bPrepareDone = false; + // Alloc resource for image acquisition + bPrepareDone = m_pobjAcqThread->PrepareForShowImg(); + if (!bPrepareDone) + { + return; + } + + // Device start acquisition and start acquisition thread + StartAcquisition(); + + LOG_DEBUG(QString("[CameraController][startCapture]虹膜相机拍图").toStdString()); + + // Do not start timer when acquisition start failed + if (!m_bAcquisitionStart) + { + return; + } } void IrisCameraController::stopCapture() { - // 获取定时器, 绑定定时函数 - disconnect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString()); - + this->StopAcquisition(); } -void IrisCameraController::getOneFaceFrm() +void IrisCameraController::SetUpAcquisitionThread() { - // 发送软触发命令(在触发模式开启时有效) - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::getLeftAndRightEyeFrame() -{ - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::OpenDevice() -{ - auto device = irisCamList.at(0); - - irisCamPtr = IGXFactory::GetInstance().OpenDeviceByUserID(device.GetUserID(), GX_ACCESS_EXCLUSIVE); - irisFeaturePtr = irisCamPtr->GetRemoteFeatureControl(); - - // 判断设备流是否大于零, 如果大于零则打开流 - int nStreamCount = irisCamPtr->GetStreamCount(); - if (nStreamCount > 0) + // if Acquisition thread is on Stop acquisition thread + if (m_pobjAcqThread != NULL) { - irisStreamPtr = irisCamPtr->OpenStream(0); - irisStreamFeaturePtr = irisStreamPtr->GetFeatureControl(); + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Release acquisition thread object + RELEASE_ALLOC_MEM(m_pobjAcqThread); } - // 建议用户在打开网络相机之后, 根据当前网络环境设置相机的流通道包长值, - // 以提高网络相机的采集性能, 设置方法参考以下代码。 - GX_DEVICE_CLASS_LIST objDeviceClass = irisCamPtr->GetDeviceInfo().GetDeviceClass(); - if(GX_DEVICE_CLASS_GEV == objDeviceClass) + // Instantiation acquisition thread + try { - // 判断设备是否支持流通道数据包功能 - if(true == irisFeaturePtr->IsImplemented("GevSCPSPacketSize")) - { - // 获取当前网络环境的最优包长值 - int nPacketSize = irisStreamPtr->GetOptimalPacketSize(); - // 将最优包长值设置为当前设备的流通道包长值 - irisFeaturePtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize); - } + m_pobjAcqThread = new CAcquisitionThread(); + m_pobjAcqThread->m_hDevice = m_hDevice; + } + catch (std::bad_alloc &e) + { + QMessageBox::about(NULL, "Allocate memory error", "Cannot allocate memory, please exit this app!"); + RELEASE_ALLOC_MEM(m_pobjAcqThread); + return; } - //设置采集模式为连续采集模式 - irisFeaturePtr->GetEnumFeature("AcquisitionMode")->SetValue("Continuous"); + return; +} - //设置触发模式关 - irisFeaturePtr->GetEnumFeature("TriggerMode")->SetValue("On"); - irisFeaturePtr->GetEnumFeature("TriggerSource")->SetValue("Software"); +void IrisCameraController::UpdateDeviceList() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Enumerate Devcie List + emStatus = GXUpdateDeviceList(&m_ui32DeviceNum, ENUMRATE_TIME_OUT); + + LOG_INFO(QString("[CameraController]枚举虹膜相机成功[%1]").arg(m_ui32DeviceNum).toStdString()); + + return; +} + +void IrisCameraController::StartAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + emStatus = GXStreamOn(m_hDevice); + + // Set acquisition thread run flag + m_pobjAcqThread->m_bAcquisitionThreadFlag = true; + + // Acquisition thread start + m_pobjAcqThread->start(); + + // isStart flag set true + m_bAcquisitionStart = true; + + return; +} + +void IrisCameraController::StopAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Turn off stream + emStatus = GXStreamOff(m_hDevice); + + // isStart flag set false + m_bAcquisitionStart = false; + + return; +} + +bool IrisCameraController::SetAcquisitionBufferNum() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + uint64_t ui64BufferNum = 0; + int64_t i64PayloadSize = 0; + + // Get device current payload size + emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &i64PayloadSize); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Set buffer quantity of acquisition queue + if (i64PayloadSize == 0) + { + return false; + } + + // Calculate a reasonable number of Buffers for different payload size + // Small ROI and high frame rate will requires more acquisition Buffer + const size_t MAX_MEMORY_SIZE = 8 * 1024 * 1024; // The maximum number of memory bytes available for allocating frame Buffer + const size_t MIN_BUFFER_NUM = 5; // Minimum frame Buffer number + const size_t MAX_BUFFER_NUM = 450; // Maximum frame Buffer number + ui64BufferNum = MAX_MEMORY_SIZE / i64PayloadSize; + ui64BufferNum = (ui64BufferNum <= MIN_BUFFER_NUM) ? MIN_BUFFER_NUM : ui64BufferNum; + ui64BufferNum = (ui64BufferNum >= MAX_BUFFER_NUM) ? MAX_BUFFER_NUM : ui64BufferNum; + + emStatus = GXSetAcqusitionBufferNumber(m_hDevice, ui64BufferNum); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Transfer buffer number to acquisition thread class for using GXDQAllBufs + m_pobjAcqThread->m_ui64AcquisitionBufferNum = ui64BufferNum; + + return true; } diff --git a/device/IrisCameraController.h b/device/IrisCameraController.h index 5d7e269..67cbe2f 100644 --- a/device/IrisCameraController.h +++ b/device/IrisCameraController.h @@ -1,11 +1,12 @@ -#ifndef IRISCAMERACONTROLLER_H +#ifndef IRISCAMERACONTROLLER_H #define IRISCAMERACONTROLLER_H #include -#include "IrisCameraCapEventHandler.h" +#include "AcquisitionThread.h" +#include "utils/UtilInclude.h" -class IrisCameraCapEventHandler; +#define ENUMRATE_TIME_OUT 200 class IrisCameraController : public QObject { @@ -14,36 +15,31 @@ explicit IrisCameraController(QObject *parent = nullptr); ~IrisCameraController(); - // 初始化并打开人脸相机 - void initIrisCamera(); void openIrisCamera(); void closeIrisCamera(); void startCapture(); void stopCapture(); - void getLeftAndRightEyeFrame(); + CAcquisitionThread * m_pobjAcqThread; + GX_DEV_HANDLE m_hDevice; ///< Device Handle + uint32_t m_ui32DeviceNum; ///< Device number enumerated - IrisCameraCapEventHandler * irisCamHandler; + bool m_bOpen; ///< Flag : camera is opened or not + bool m_bAcquisitionStart; ///< Flag : camera is acquiring or not private: - GxIAPICPP::gxdeviceinfo_vector irisCamList; - - CGXDevicePointer irisCamPtr; ///< 设备句柄 - - CGXStreamPointer irisStreamPtr; ///< 左眼设备流 - - CGXFeatureControlPointer irisFeaturePtr; ///< 左眼属性控制器 - - CGXFeatureControlPointer irisStreamFeaturePtr; ///< 左眼流层控制器对象 - - void OpenDevice(); + // 初始化并打开人脸相机 + void initIrisCameraController(); + void SetUpAcquisitionThread(); + void UpdateDeviceList(); + bool SetAcquisitionBufferNum(); + void StartAcquisition(); + void StopAcquisition(); signals: - -public slots: - void getOneFaceFrm(); - + void irisCameraInitError(); + void irisCameraTermError(); }; #endif // IRISCAMERACONTROLLER_H diff --git a/device/device.pri b/device/device.pri index d1330a0..583721b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,13 +1,14 @@ HEADERS += $$PWD/IrisCameraController.h -HEADERS += $$PWD/IrisCameraCapEventHandler.h -#HEADERS += $$PWD/iris/IrisRegistProcess.h +#HEADERS += $$PWD/IrisCameraCapEventHandler.h +HEADERS += $$PWD/Common.h +HEADERS += $$PWD/AcquisitionThread.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h SOURCES += $$PWD/IrisCameraController.cpp -SOURCES += $$PWD/IrisCameraCapEventHandler.cpp -#SOURCES += $$PWD/iris/IrisRegistProcess.cpp +#SOURCES += $$PWD/IrisCameraCapEventHandler.cpp +SOURCES += $$PWD/AcquisitionThread.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 38f54fe..e4c8a02 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -11,7 +11,7 @@ // 连接算法服务 clientUtil = new SocketClientUtil(this); - clientUtil->connect("192.168.83.223", 50007); + clientUtil->connect(SettingConfig::getInstance().DEBUG_SEGMENT_IP, 50007); // 调用socket发送消息 connect(this, &IrisRecogProcess::sendDataToExract, clientUtil, &SocketClientUtil::sendData); @@ -43,18 +43,18 @@ continue; } - // 1. 图像栈中没有图像则直接返回 - if (ProMemory::getInstance().isIrisQueueEmpty() == true) + // 1. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 + if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) { - qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); + qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } - // 2. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 - if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) + // 2. 图像栈中没有图像则直接返回 + if (ProMemory::getInstance().isIrisQueueEmpty() == true) { - qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); + qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } @@ -73,7 +73,7 @@ int findEyeLast = timer.elapsed(); qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); -// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.matData = cv::imread("/home/casic/code/irisLogs/145333.552.bmp", 0); // irisInfo.hasEye = true; // 4.1 没有找到眼睛则返回 @@ -117,11 +117,10 @@ // 缩放到320 * 240 cv::resize(segMat, segMat, cv::Size(SettingConfig::getInstance().IRIS_WIDTH * 0.5, SettingConfig::getInstance().IRIS_HEIGHT * 0.5)); - - // std::string filename = QString("%1\\%2\\%3-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - // cv::imwrite(filename, segMat); - // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - +/* + std::string filename = QString("%1/%2/%3-seg.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(filename, segMat); +*/ int segMatSize = segMat.cols * segMat.rows; QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 @@ -167,9 +166,9 @@ // 成功接收后清除缓存区 clientUtil->resetRecvBuffer(); /* - std::string pupilSeg = QString("%1\\%2\\%3-pupil-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string maskSeg = QString("%1\\%2\\%3-mask-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string irisSeg = QString("%1\\%2\\%3-iris-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string pupilSeg = QString("%1/%2/%3-pupil-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); cv::imwrite(pupilSeg, pupil); cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); @@ -196,12 +195,20 @@ CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; irisInfo = casic::iris::CasicIrisInterface::getInstance().irisEncode(irisInfo); /* - std::string codeFilename = QString("%1\\%2\\%3-code.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string codeFilename = QString("%1/%2/%3-code.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string maskFilename = QString("%1/%2/%3-mask.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); */ + if (irisInfo.postProcSucc == false) { + qDebug() << "算法post process失败,暂停200ms"; + + addOneTryCount(); + this->msleep(THREAD_MSLEEP); // 200ms后再判断 + continue; + } + // 从编码中提取特征值 irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); @@ -211,6 +218,8 @@ CasicIrisRecState::getInstance().extractTmLast = encodeLast; CasicIrisRecState::getInstance().recogTimeLast += encodeLast; +// cv::imwrite(QString("%1/%2/%3.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(), irisInfo.matData); + // 开始匹配 timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) @@ -219,7 +228,7 @@ float score = casic::iris::CasicIrisInterface::getInstance().calculatePairPoints(feature.irisFeatureCode, irisInfo.irisFeatureCode); // 计算压缩编码的比较值 -// cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); +// cv::imwrite(QString("%1/%2/%3-%4.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; @@ -251,7 +260,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } @@ -268,7 +277,7 @@ CasicIrisRecState::getInstance().tryCount = 0; this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); emit failedMatchedIris(); @@ -290,7 +299,7 @@ // 识别失败时暂停工作 待返回识别界面时再开始工作和拍图 this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); } } else if (ProMemory::getInstance().appState == AppConstants::ApplicationState::STATE_WORKING) @@ -298,7 +307,8 @@ CasicIrisRecState::getInstance().noEyeCount++; // 如果在工作状态 则超过一定次数后返回待机 - if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT) + if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT && + SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT > 0) { // 发送信号待机 emit backToLockScreen(); diff --git a/device/iris/IrisRecogProcess.h b/device/iris/IrisRecogProcess.h index 9a3eec6..e21c1a7 100644 --- a/device/iris/IrisRecogProcess.h +++ b/device/iris/IrisRecogProcess.h @@ -1,4 +1,4 @@ -#ifndef IRISRECOGPROCESS_H +#ifndef IRISRECOGPROCESS_H #define IRISRECOGPROCESS_H #define THREAD_MSLEEP 200 @@ -10,6 +10,7 @@ #include "ProMemory.h" #include "device/iris/CasicIrisRecState.h" +#include "casic/iris/CasicIrisInterface.h" class IrisRecogProcess : public QThread { diff --git a/main.cpp b/main.cpp index 9052ddb..3bfb1c6 100644 --- a/main.cpp +++ b/main.cpp @@ -1,11 +1,11 @@ -#include "MainWindowForm.h" - -#include - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - MainWindowForm w; - w.show(); - return a.exec(); -} +#include "MainWindowForm.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindowForm w; + w.show(); + return a.exec(); +} diff --git a/utils/ImageUtil.cpp b/utils/ImageUtil.cpp index ff77331..d40ea79 100644 --- a/utils/ImageUtil.cpp +++ b/utils/ImageUtil.cpp @@ -1,107 +1,107 @@ -#include "ImageUtil.h" - -ImageUtil::ImageUtil() -{ - -} - -QImage ImageUtil::MatImageToQImage(const cv::Mat &src) -{ - //CV_8UC1 8位无符号的单通道---灰度图片 - if(src.type() == CV_8UC1) - { - QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); - return qImage; - } - //为3通道的彩色图片 - else if(src.type() == CV_8UC3) - { - //得到图像的的首地址 - const uchar *pSrc = (const uchar*)src.data; - //以src构造图片 - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); - } - //四通道图片, 带Alpha通道的RGB彩色图像 - else if(src.type() == CV_8UC4) - { - const uchar *pSrc = (const uchar*)src.data; - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); - //返回图像的子区域作为一个新图像 - return qImage.copy(); - } - else - { - return QImage(); - } -} - -cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) -{ - cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); - return img; -} - -cv::Mat ImageUtil::QImageToMat(QImage image) -{ - cv::Mat mat; - switch(image.format()) - { - case QImage::Format_ARGB32: - case QImage::Format_RGB32: - case QImage::Format_ARGB32_Premultiplied: - mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_RGB888: - mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); - cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); - break; - case QImage::Format_Indexed8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_Grayscale8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); - break; - - default: - break; - } - - mat = mat.clone(); - - return mat; -} - -/* -QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) -{ - QImage qImage(data, width, height, format); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); -} - -QString ImageUtil::QImageToBase64(QImage image) -{ - QByteArray ba; - QBuffer buf(&ba); - image.save(&buf, "bmp"); - QString base64String = ba.toBase64(); - return base64String; -} - -cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) -{ - cv::Mat matClone = src.clone(); - cv::Rect bigRect; - - bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; - bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; - bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; - bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; - - cv::Mat roi = matClone(bigRect); - - return roi; -} -*/ +#include "ImageUtil.h" + +ImageUtil::ImageUtil() +{ + +} + +QImage ImageUtil::MatImageToQImage(const cv::Mat &src) +{ + //CV_8UC1 8位无符号的单通道---灰度图片 + if(src.type() == CV_8UC1) + { + QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); + return qImage; + } + //为3通道的彩色图片 + else if(src.type() == CV_8UC3) + { + //得到图像的的首地址 + const uchar *pSrc = (const uchar*)src.data; + //以src构造图片 + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); + } + //四通道图片, 带Alpha通道的RGB彩色图像 + else if(src.type() == CV_8UC4) + { + const uchar *pSrc = (const uchar*)src.data; + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); + //返回图像的子区域作为一个新图像 + return qImage.copy(); + } + else + { + return QImage(); + } +} + +cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) +{ + cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); + return img; +} + +cv::Mat ImageUtil::QImageToMat(QImage image) +{ + cv::Mat mat; + switch(image.format()) + { + case QImage::Format_ARGB32: + case QImage::Format_RGB32: + case QImage::Format_ARGB32_Premultiplied: + mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_RGB888: + mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); + cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); + break; + case QImage::Format_Indexed8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_Grayscale8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); + break; + + default: + break; + } + + mat = mat.clone(); + + return mat; +} + +/* +QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) +{ + QImage qImage(data, width, height, format); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); +} + +QString ImageUtil::QImageToBase64(QImage image) +{ + QByteArray ba; + QBuffer buf(&ba); + image.save(&buf, "bmp"); + QString base64String = ba.toBase64(); + return base64String; +} + +cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) +{ + cv::Mat matClone = src.clone(); + cv::Rect bigRect; + + bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; + bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; + bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; + bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; + + cv::Mat roi = matClone(bigRect); + + return roi; +} +*/ diff --git a/utils/ImageUtil.h b/utils/ImageUtil.h index d9bf00a..4b702f4 100644 --- a/utils/ImageUtil.h +++ b/utils/ImageUtil.h @@ -1,23 +1,23 @@ -#ifndef IMAGEUTIL_H -#define IMAGEUTIL_H - -#include -#include -#include "opencv2/opencv.hpp" - -class ImageUtil -{ -public: - ImageUtil(); - - static QImage MatImageToQImage(const cv::Mat &src); -// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); - - static cv::Mat ucharToMat(unsigned char * data, int row, int col); - static cv::Mat QImageToMat(QImage image); -// static QString QImageToBase64(QImage image); - -// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); -}; - -#endif // IMAGEUTIL_H +#ifndef IMAGEUTIL_H +#define IMAGEUTIL_H + +#include +#include +#include "opencv2/opencv.hpp" + +class ImageUtil +{ +public: + ImageUtil(); + + static QImage MatImageToQImage(const cv::Mat &src); +// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); + + static cv::Mat ucharToMat(unsigned char * data, int row, int col); + static cv::Mat QImageToMat(QImage image); +// static QString QImageToBase64(QImage image); + +// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); +}; + +#endif // IMAGEUTIL_H diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp index 663db0f..05c4c68 100644 --- a/utils/SettingConfig.cpp +++ b/utils/SettingConfig.cpp @@ -1,4 +1,4 @@ -#include "SettingConfig.h" +#include "SettingConfig.h" #include SettingConfig::SettingConfig() @@ -34,6 +34,9 @@ LOG_FILE = getProperty("log", "logFile").toString(); LOG_LEVEL = getProperty("log", "logLevel").toString(); + + DEBUG_CAMERA_ROTATE = getProperty("debug", "cameraRotate").toString(); + DEBUG_SEGMENT_IP = getProperty("debug", "segmentIp").toString(); } diff --git a/utils/SettingConfig.h b/utils/SettingConfig.h index b65f553..c35d6ab 100644 --- a/utils/SettingConfig.h +++ b/utils/SettingConfig.h @@ -1,4 +1,4 @@ -#ifndef SETTINGCONFIG_H +#ifndef SETTINGCONFIG_H #define SETTINGCONFIG_H #include @@ -55,6 +55,9 @@ QString LOG_FILE; QString LOG_LEVEL; + QString DEBUG_CAMERA_ROTATE; + QString DEBUG_SEGMENT_IP; + private: SettingConfig(); diff --git a/utils/SocketClientUtil.cpp b/utils/SocketClientUtil.cpp index d539d64..20b8869 100644 --- a/utils/SocketClientUtil.cpp +++ b/utils/SocketClientUtil.cpp @@ -1,9 +1,10 @@ -#include "SocketClientUtil.h" +#include "SocketClientUtil.h" #include "utils/ByteUtil.h" SocketClientUtil::SocketClientUtil(QObject *parent) : QObject(parent) { QObject::connect(&objClient, &QTcpSocket::readyRead, this, &SocketClientUtil::readData); + QObject::connect(&objClient, &QTcpSocket::disconnected, this, &SocketClientUtil::socketReconnect); } void SocketClientUtil::connect(QString host, int port) @@ -16,6 +17,10 @@ void SocketClientUtil::closeConnect() { + QObject::disconnect(&objClient, &QTcpSocket::readyRead, this, &SocketClientUtil::readData); + QObject::disconnect(&objClient, &QTcpSocket::disconnected, this, &SocketClientUtil::socketReconnect); + + objClient.disconnectFromHost(); objClient.close(); } @@ -45,3 +50,9 @@ emit this->responseReaded(); } } + +void SocketClientUtil::socketReconnect() +{ + objClient.close(); + objClient.connectToHost(this->host, this->port); +} diff --git a/utils/SocketClientUtil.h b/utils/SocketClientUtil.h index 96b60e0..8bd1b8c 100644 --- a/utils/SocketClientUtil.h +++ b/utils/SocketClientUtil.h @@ -1,4 +1,4 @@ -#ifndef SOCKETCLIENTUTIL_H +#ifndef SOCKETCLIENTUTIL_H #define SOCKETCLIENTUTIL_H #include @@ -30,6 +30,7 @@ public slots: void readData(); void sendData(QByteArray data); + void socketReconnect(); }; diff --git a/utils/TimeCounterUtil.cpp b/utils/TimeCounterUtil.cpp index 275945f..78c3d69 100644 --- a/utils/TimeCounterUtil.cpp +++ b/utils/TimeCounterUtil.cpp @@ -1,8 +1,9 @@ -#include "TimeCounterUtil.h" - -TimeCounterUtil::TimeCounterUtil() -{ - faceCapCounter = new QTimer(); - irisCapCounter = new QTimer(); - clockCounter = new QTimer(); -} +#include "TimeCounterUtil.h" + +TimeCounterUtil::TimeCounterUtil() +{ + faceCapCounter = new QTimer(); + irisCapCounter = new QTimer(); + clockCounter = new QTimer(); + videoCounter = new QTimer(); +} diff --git a/utils/TimeCounterUtil.h b/utils/TimeCounterUtil.h index 28b29f1..91f8da0 100644 --- a/utils/TimeCounterUtil.h +++ b/utils/TimeCounterUtil.h @@ -1,29 +1,30 @@ -#ifndef TIMECOUNTERUTIL_H -#define TIMECOUNTERUTIL_H - -#include -#include - -class TimeCounterUtil : public QObject -{ -public: - - ~TimeCounterUtil() {}; - TimeCounterUtil(const TimeCounterUtil&)=delete; - TimeCounterUtil& operator=(const TimeCounterUtil&)=delete; - - static TimeCounterUtil& getInstance() { - static TimeCounterUtil instance; - return instance; - } - - QTimer * faceCapCounter; - QTimer * irisCapCounter; - QTimer * clockCounter; - -private: - TimeCounterUtil(); - -}; - -#endif // TIMECOUNTERUTIL_H +#ifndef TIMECOUNTERUTIL_H +#define TIMECOUNTERUTIL_H + +#include +#include + +class TimeCounterUtil : public QObject +{ +public: + + ~TimeCounterUtil() {}; + TimeCounterUtil(const TimeCounterUtil&)=delete; + TimeCounterUtil& operator=(const TimeCounterUtil&)=delete; + + static TimeCounterUtil& getInstance() { + static TimeCounterUtil instance; + return instance; + } + + QTimer * faceCapCounter; + QTimer * irisCapCounter; + QTimer * clockCounter; + QTimer * videoCounter; // show video images on main window + +private: + TimeCounterUtil(); + +}; + +#endif // TIMECOUNTERUTIL_H diff --git a/utils/UtilInclude.h b/utils/UtilInclude.h index 0b329c9..bea17be 100644 --- a/utils/UtilInclude.h +++ b/utils/UtilInclude.h @@ -1,15 +1,15 @@ -#ifndef UTILINCLUDE_H -#define UTILINCLUDE_H - -#include -#include "ByteUtil.h" -#include "ImageUtil.h" -#include "LogUtil.h" -#include "SettingConfig.h" -#include "SocketClientUtil.h" -#include "SpeakerUtil.h" -#include "TimeCounterUtil.h" -//#include "UDPClientUtil.h" -//#include "HttpRequestUtil.h" - -#endif // UTILINCLUDE_H +#ifndef UTILINCLUDE_H +#define UTILINCLUDE_H + +#include +#include "ByteUtil.h" +#include "ImageUtil.h" +#include "LogUtil.h" +#include "SettingConfig.h" +#include "SocketClientUtil.h" +#include "SpeakerUtil.h" +#include "TimeCounterUtil.h" +//#include "UDPClientUtil.h" +//#include "HttpRequestUtil.h" + +#endif // UTILINCLUDE_H diff --git a/utils/id/IdWorker.h b/utils/id/IdWorker.h index 6c48aa9..079bbcb 100644 --- a/utils/id/IdWorker.h +++ b/utils/id/IdWorker.h @@ -1,218 +1,218 @@ -#ifndef _JW_CORE_ID_WORKER_H_ -#define _JW_CORE_ID_WORKER_H_ - -#include -#include -#include -#include -#include -#include "Noncopyable.h" -#include "Singleton.h" - -// 如果不使用 mutex, 则开启下面这个定义, 但是我发现, 还是开启 mutex 功能, 速度比较快 -// #define SNOWFLAKE_ID_WORKER_NO_LOCK - -namespace Jiawa { - - /** - * @brief 核心 - * 核心功能 - */ - namespace Core { - - /** - * @brief 分布式id生成类 - * https://segmentfault.com/a/1190000011282426 - * https://github.com/twitter/snowflake/blob/snowflake-2010/src/main/scala/com/twitter/service/snowflake/IdWorker.scala - * - * 64bit id: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 - * || || || | | | - * |└---------------------------时间戳--------------------------┘└中心-┘└机器-┘ └----序列号----┘ - * | - * 不用 - * SnowFlake的优点: 整体上按照时间自增排序, 并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分), 并且效率较高, 经测试, SnowFlake每秒能够产生26万ID左右. - */ - class SnowflakeIdWorker : private Noncopyable { - - // 实现单例 - friend class Singleton; - - public: - typedef unsigned int UInt; - typedef unsigned long long int UInt64; - -#ifdef SNOWFLAKE_ID_WORKER_NO_LOCK - typedef std::atomic AtomicUInt; - typedef std::atomic AtomicUInt64; -#else - typedef UInt AtomicUInt; - typedef UInt64 AtomicUInt64; -#endif - - void setWorkerId(UInt workerId) { - this->workerId = workerId; - } - - void setDatacenterId(UInt datacenterId) { - this->datacenterId = datacenterId; - } - - UInt64 getId() { - return nextId(); - } - - /** - * 获得下一个ID (该方法是线程安全的) - * - * @return SnowflakeId - */ - UInt64 nextId() { -#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK - std::unique_lock lock{ mutex }; - AtomicUInt64 timestamp{ 0 }; -#else - static AtomicUInt64 timestamp{ 0 }; -#endif - timestamp = timeGen(); - - // 如果当前时间小于上一次ID生成的时间戳, 说明系统时钟回退过这个时候应当抛出异常 - if (timestamp < lastTimestamp) { - std::ostringstream s; - s << "clock moved backwards. Refusing to generate id for " << lastTimestamp - timestamp << " milliseconds"; - throw std::exception(std::runtime_error(s.str())); - } - - if (lastTimestamp == timestamp) { - // 如果是同一时间生成的, 则进行毫秒内序列 - sequence = (sequence + 1) & sequenceMask; - if (0 == sequence) { - // 毫秒内序列溢出, 阻塞到下一个毫秒,获得新的时间戳 - timestamp = tilNextMillis(lastTimestamp); - } - } else { - sequence = 0; - } - -#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK - lastTimestamp = timestamp; -#else - lastTimestamp = timestamp.load(); -#endif - - // 移位并通过或运算拼到一起组成64位的ID - return ((timestamp - twepoch) << timestampLeftShift) - | (datacenterId << datacenterIdShift) - | (workerId << workerIdShift) - | sequence; - } - - protected: - SnowflakeIdWorker() : workerId(0), datacenterId(0), sequence(0), lastTimestamp(0) { } - - /** - * 返回以毫秒为单位的当前时间 - * - * @return 当前时间(毫秒) - */ - UInt64 timeGen() const { - auto t = std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()); - return t.time_since_epoch().count(); - } - - /** - * 阻塞到下一个毫秒, 直到获得新的时间戳 - * - * @param lastTimestamp 上次生成ID的时间截 - * @return 当前时间戳 - */ - UInt64 tilNextMillis(UInt64 lastTimestamp) const { - UInt64 timestamp = timeGen(); - while (timestamp <= lastTimestamp) { - timestamp = timeGen(); - } - return timestamp; - } - - private: - -#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK - std::mutex mutex; -#endif - - /** - * 开始时间截 (2018-01-01 00:00:00.000) - */ - const UInt64 twepoch = 1514736000000; - - /** - * 机器id所占的位数 - */ - const UInt workerIdBits = 5; - - /** - * 数据中心id所占的位数 - */ - const UInt datacenterIdBits = 5; - - /** - * 序列所占的位数 - */ - const UInt sequenceBits = 12; - - /** - * 机器ID向左移12位 - */ - const UInt workerIdShift = sequenceBits; - - /** - * 数据标识id向左移17位 - */ - const UInt datacenterIdShift = workerIdShift + workerIdBits; - - /** - * 时间截向左移22位 - */ - const UInt timestampLeftShift = datacenterIdShift + datacenterIdBits; - - /** - * 支持的最大机器id, 结果是31 - */ - const UInt maxWorkerId = -1 ^ (-1 << workerIdBits); - - /** - * 支持的最大数据中心id, 结果是31 - */ - const UInt maxDatacenterId = -1 ^ (-1 << datacenterIdBits); - - /** - * 生成序列的掩码, 这里为4095 - */ - const UInt sequenceMask = -1 ^ (-1 << sequenceBits); - - /** - * 工作机器id(0~31) - */ - UInt workerId; - - /** - * 数据中心id(0~31) - */ - UInt datacenterId; - - /** - * 毫秒内序列(0~4095) - */ - AtomicUInt sequence{ 0 }; - - /** - * 上次生成ID的时间截 - */ - AtomicUInt64 lastTimestamp{ 0 }; - - }; - - typedef SnowflakeIdWorker IdWorker; - } -} - -#endif // _JW_CORE_ID_WORKER_H_ +#ifndef _JW_CORE_ID_WORKER_H_ +#define _JW_CORE_ID_WORKER_H_ + +#include +#include +#include +#include +#include +#include "Noncopyable.h" +#include "Singleton.h" + +// 如果不使用 mutex, 则开启下面这个定义, 但是我发现, 还是开启 mutex 功能, 速度比较快 +// #define SNOWFLAKE_ID_WORKER_NO_LOCK + +namespace Jiawa { + + /** + * @brief 核心 + * 核心功能 + */ + namespace Core { + + /** + * @brief 分布式id生成类 + * https://segmentfault.com/a/1190000011282426 + * https://github.com/twitter/snowflake/blob/snowflake-2010/src/main/scala/com/twitter/service/snowflake/IdWorker.scala + * + * 64bit id: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + * || || || | | | + * |└---------------------------时间戳--------------------------┘└中心-┘└机器-┘ └----序列号----┘ + * | + * 不用 + * SnowFlake的优点: 整体上按照时间自增排序, 并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分), 并且效率较高, 经测试, SnowFlake每秒能够产生26万ID左右. + */ + class SnowflakeIdWorker : private Noncopyable { + + // 实现单例 + friend class Singleton; + + public: + typedef unsigned int UInt; + typedef unsigned long long int UInt64; + +#ifdef SNOWFLAKE_ID_WORKER_NO_LOCK + typedef std::atomic AtomicUInt; + typedef std::atomic AtomicUInt64; +#else + typedef UInt AtomicUInt; + typedef UInt64 AtomicUInt64; +#endif + + void setWorkerId(UInt workerId) { + this->workerId = workerId; + } + + void setDatacenterId(UInt datacenterId) { + this->datacenterId = datacenterId; + } + + UInt64 getId() { + return nextId(); + } + + /** + * 获得下一个ID (该方法是线程安全的) + * + * @return SnowflakeId + */ + UInt64 nextId() { +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + std::unique_lock lock{ mutex }; + AtomicUInt64 timestamp{ 0 }; +#else + static AtomicUInt64 timestamp{ 0 }; +#endif + timestamp = timeGen(); + + // 如果当前时间小于上一次ID生成的时间戳, 说明系统时钟回退过这个时候应当抛出异常 + if (timestamp < lastTimestamp) { + std::ostringstream s; + s << "clock moved backwards. Refusing to generate id for " << lastTimestamp - timestamp << " milliseconds"; + throw std::exception(std::runtime_error(s.str())); + } + + if (lastTimestamp == timestamp) { + // 如果是同一时间生成的, 则进行毫秒内序列 + sequence = (sequence + 1) & sequenceMask; + if (0 == sequence) { + // 毫秒内序列溢出, 阻塞到下一个毫秒,获得新的时间戳 + timestamp = tilNextMillis(lastTimestamp); + } + } else { + sequence = 0; + } + +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + lastTimestamp = timestamp; +#else + lastTimestamp = timestamp.load(); +#endif + + // 移位并通过或运算拼到一起组成64位的ID + return ((timestamp - twepoch) << timestampLeftShift) + | (datacenterId << datacenterIdShift) + | (workerId << workerIdShift) + | sequence; + } + + protected: + SnowflakeIdWorker() : workerId(0), datacenterId(0), sequence(0), lastTimestamp(0) { } + + /** + * 返回以毫秒为单位的当前时间 + * + * @return 当前时间(毫秒) + */ + UInt64 timeGen() const { + auto t = std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()); + return t.time_since_epoch().count(); + } + + /** + * 阻塞到下一个毫秒, 直到获得新的时间戳 + * + * @param lastTimestamp 上次生成ID的时间截 + * @return 当前时间戳 + */ + UInt64 tilNextMillis(UInt64 lastTimestamp) const { + UInt64 timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + private: + +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + std::mutex mutex; +#endif + + /** + * 开始时间截 (2018-01-01 00:00:00.000) + */ + const UInt64 twepoch = 1514736000000; + + /** + * 机器id所占的位数 + */ + const UInt workerIdBits = 5; + + /** + * 数据中心id所占的位数 + */ + const UInt datacenterIdBits = 5; + + /** + * 序列所占的位数 + */ + const UInt sequenceBits = 12; + + /** + * 机器ID向左移12位 + */ + const UInt workerIdShift = sequenceBits; + + /** + * 数据标识id向左移17位 + */ + const UInt datacenterIdShift = workerIdShift + workerIdBits; + + /** + * 时间截向左移22位 + */ + const UInt timestampLeftShift = datacenterIdShift + datacenterIdBits; + + /** + * 支持的最大机器id, 结果是31 + */ + const UInt maxWorkerId = -1 ^ (-1 << workerIdBits); + + /** + * 支持的最大数据中心id, 结果是31 + */ + const UInt maxDatacenterId = -1 ^ (-1 << datacenterIdBits); + + /** + * 生成序列的掩码, 这里为4095 + */ + const UInt sequenceMask = -1 ^ (-1 << sequenceBits); + + /** + * 工作机器id(0~31) + */ + UInt workerId; + + /** + * 数据中心id(0~31) + */ + UInt datacenterId; + + /** + * 毫秒内序列(0~4095) + */ + AtomicUInt sequence{ 0 }; + + /** + * 上次生成ID的时间截 + */ + AtomicUInt64 lastTimestamp{ 0 }; + + }; + + typedef SnowflakeIdWorker IdWorker; + } +} + +#endif // _JW_CORE_ID_WORKER_H_ diff --git a/utils/id/Noncopyable.h b/utils/id/Noncopyable.h index d87f58a..4fc555a 100644 --- a/utils/id/Noncopyable.h +++ b/utils/id/Noncopyable.h @@ -1,31 +1,31 @@ -#ifndef _JW_CORE_NONCOPYABLE_H_ -#define _JW_CORE_NONCOPYABLE_H_ - - -// Private copy constructor and copy assignment ensure classes derived from -// class noncopyable cannot be copied. - -namespace Jiawa { - namespace Core { - - // protection from unintended ADL(Argument Dependent Lookup) - namespace Noncopyable_ { - - class Noncopyable - { - protected: - Noncopyable() = default; - ~Noncopyable() = default; - - Noncopyable(const Noncopyable&) = delete; - Noncopyable(const Noncopyable&&) = delete; - Noncopyable& operator=(const Noncopyable&) = delete; - Noncopyable& operator=(const Noncopyable&&) = delete; - }; - } - - typedef Noncopyable_::Noncopyable Noncopyable; - } -} - -#endif // _JW_CORE_NONCOPYABLE_H_ +#ifndef _JW_CORE_NONCOPYABLE_H_ +#define _JW_CORE_NONCOPYABLE_H_ + + +// Private copy constructor and copy assignment ensure classes derived from +// class noncopyable cannot be copied. + +namespace Jiawa { + namespace Core { + + // protection from unintended ADL(Argument Dependent Lookup) + namespace Noncopyable_ { + + class Noncopyable + { + protected: + Noncopyable() = default; + ~Noncopyable() = default; + + Noncopyable(const Noncopyable&) = delete; + Noncopyable(const Noncopyable&&) = delete; + Noncopyable& operator=(const Noncopyable&) = delete; + Noncopyable& operator=(const Noncopyable&&) = delete; + }; + } + + typedef Noncopyable_::Noncopyable Noncopyable; + } +} + +#endif // _JW_CORE_NONCOPYABLE_H_ diff --git a/utils/id/Singleton.h b/utils/id/Singleton.h index d1c0553..daad45c 100644 --- a/utils/id/Singleton.h +++ b/utils/id/Singleton.h @@ -1,60 +1,60 @@ -#ifndef _JW_CORE_SINGLETON_H_ -#define _JW_CORE_SINGLETON_H_ - -namespace Jiawa { - namespace Core { - - // boost/container/detail/singleton.hpp - // http://blog.csdn.net/fullsail/article/details/8483106 - // T must be: no-throw default constructible and no-throw destructible - template - class Singleton { - private: - Singleton() = default; - ~Singleton() = default; - - private: - struct object_creator - { - // This constructor does nothing more than ensure that instance() - // is called before main() begins, thus creating the static - // T object before multithreading race issues can come up. - object_creator() { Singleton::instance(); } - inline void do_nothing() const { } - }; - static object_creator create_object; - - private: - Singleton(const Singleton&) = delete; - Singleton(const Singleton&&) = delete; - Singleton& operator=(const Singleton&) = delete; - Singleton& operator=(const Singleton&&) = delete; - - public: - typedef T object_type; - - // If, at any point (in user code), Singleton::instance() - // is called, then the following function is instantiated. - static object_type& instance() - { - // This is the object that we return a reference to. - // It is guaranteed to be created before main() begins because of - // the next line. - static object_type obj; - - // The following line does nothing else than force the instantiation - // of Singleton::create_object, whose constructor is - // called before main() begins. - create_object.do_nothing(); - - return obj; - } - }; - - template - typename Singleton::object_creator Singleton::create_object; - } -} - -#endif // _JW_CORE_SINGLETON_H_ - +#ifndef _JW_CORE_SINGLETON_H_ +#define _JW_CORE_SINGLETON_H_ + +namespace Jiawa { + namespace Core { + + // boost/container/detail/singleton.hpp + // http://blog.csdn.net/fullsail/article/details/8483106 + // T must be: no-throw default constructible and no-throw destructible + template + class Singleton { + private: + Singleton() = default; + ~Singleton() = default; + + private: + struct object_creator + { + // This constructor does nothing more than ensure that instance() + // is called before main() begins, thus creating the static + // T object before multithreading race issues can come up. + object_creator() { Singleton::instance(); } + inline void do_nothing() const { } + }; + static object_creator create_object; + + private: + Singleton(const Singleton&) = delete; + Singleton(const Singleton&&) = delete; + Singleton& operator=(const Singleton&) = delete; + Singleton& operator=(const Singleton&&) = delete; + + public: + typedef T object_type; + + // If, at any point (in user code), Singleton::instance() + // is called, then the following function is instantiated. + static object_type& instance() + { + // This is the object that we return a reference to. + // It is guaranteed to be created before main() begins because of + // the next line. + static object_type obj; + + // The following line does nothing else than force the instantiation + // of Singleton::create_object, whose constructor is + // called before main() begins. + create_object.do_nothing(); + + return obj; + } + }; + + template + typename Singleton::object_creator Singleton::create_object; + } +} + +#endif // _JW_CORE_SINGLETON_H_ + diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/device/IrisCameraCapEventHandler.h b/device/IrisCameraCapEventHandler.h index 8b976c5..94f5594 100644 --- a/device/IrisCameraCapEventHandler.h +++ b/device/IrisCameraCapEventHandler.h @@ -1,10 +1,9 @@ -#ifndef IRISCAMERACAPEVENTHANDLER_H +#ifndef IRISCAMERACAPEVENTHANDLER_H #define IRISCAMERACAPEVENTHANDLER_H #include #include -#include "include/opencv2/opencv.hpp" -#include "include/daheng/GalaxyIncludes.h" +#include #include "casic/iris/CasicIrisInterface.h" #include "ProMemory.h" diff --git a/device/IrisCameraController.cpp b/device/IrisCameraController.cpp index 0928176..4eea013 100644 --- a/device/IrisCameraController.cpp +++ b/device/IrisCameraController.cpp @@ -1,8 +1,8 @@ -#include "IrisCameraController.h" +#include "IrisCameraController.h" IrisCameraController::IrisCameraController(QObject *parent) : QObject(parent) { - this->irisCamHandler = new IrisCameraCapEventHandler(this); + initIrisCameraController(); } IrisCameraController::~IrisCameraController() { @@ -10,101 +10,204 @@ } -void IrisCameraController::initIrisCamera() +void IrisCameraController::initIrisCameraController() { - IGXFactory::GetInstance().Init(); + // Init GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXInitLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraInitError(); + LOG_ERROR("[CameraController]初始化虹膜相机失败"); + return ; + } + LOG_INFO("[CameraController]初始化虹膜相机成功"); //枚举设备 - IGXFactory::GetInstance().UpdateDeviceList(1000, irisCamList); - - this->OpenDevice(); + UpdateDeviceList(); } void IrisCameraController::openIrisCamera() { - //设置Buffer处理模式 - irisStreamFeaturePtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst"); + GX_STATUS emStatus = GX_STATUS_SUCCESS; - //注册回调函数 - irisStreamPtr->RegisterCaptureCallback(irisCamHandler, &irisCamPtr); + if (m_ui32DeviceNum > 0) { + emStatus = GXOpenDeviceByIndex(1, &m_hDevice); - //开启流层通道 - irisStreamPtr->StartGrab(); + if (emStatus == GX_STATUS_SUCCESS) { + LOG_INFO("[CameraController]开启虹膜相机成功"); - //发送开采命令 - irisFeaturePtr->GetCommandFeature("AcquisitionStart")->Execute(); + // isOpen flag set true + m_bOpen = true; - // 启动定时器 - TimeCounterUtil::getInstance().irisCapCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); // 50ms执行一次定时器 + SetUpAcquisitionThread(); + } + } + + return; } void IrisCameraController::closeIrisCamera() { - + // Release GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXCloseLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraTermError(); + } } void IrisCameraController::startCapture() { // 获取定时器, 绑定定时函数 - connect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString()); + bool bSetDone = false; + // Set acquisition buffer number + bSetDone = SetAcquisitionBufferNum(); + if (!bSetDone) + { + return; + } + + bool bPrepareDone = false; + // Alloc resource for image acquisition + bPrepareDone = m_pobjAcqThread->PrepareForShowImg(); + if (!bPrepareDone) + { + return; + } + + // Device start acquisition and start acquisition thread + StartAcquisition(); + + LOG_DEBUG(QString("[CameraController][startCapture]虹膜相机拍图").toStdString()); + + // Do not start timer when acquisition start failed + if (!m_bAcquisitionStart) + { + return; + } } void IrisCameraController::stopCapture() { - // 获取定时器, 绑定定时函数 - disconnect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString()); - + this->StopAcquisition(); } -void IrisCameraController::getOneFaceFrm() +void IrisCameraController::SetUpAcquisitionThread() { - // 发送软触发命令(在触发模式开启时有效) - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::getLeftAndRightEyeFrame() -{ - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::OpenDevice() -{ - auto device = irisCamList.at(0); - - irisCamPtr = IGXFactory::GetInstance().OpenDeviceByUserID(device.GetUserID(), GX_ACCESS_EXCLUSIVE); - irisFeaturePtr = irisCamPtr->GetRemoteFeatureControl(); - - // 判断设备流是否大于零, 如果大于零则打开流 - int nStreamCount = irisCamPtr->GetStreamCount(); - if (nStreamCount > 0) + // if Acquisition thread is on Stop acquisition thread + if (m_pobjAcqThread != NULL) { - irisStreamPtr = irisCamPtr->OpenStream(0); - irisStreamFeaturePtr = irisStreamPtr->GetFeatureControl(); + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Release acquisition thread object + RELEASE_ALLOC_MEM(m_pobjAcqThread); } - // 建议用户在打开网络相机之后, 根据当前网络环境设置相机的流通道包长值, - // 以提高网络相机的采集性能, 设置方法参考以下代码。 - GX_DEVICE_CLASS_LIST objDeviceClass = irisCamPtr->GetDeviceInfo().GetDeviceClass(); - if(GX_DEVICE_CLASS_GEV == objDeviceClass) + // Instantiation acquisition thread + try { - // 判断设备是否支持流通道数据包功能 - if(true == irisFeaturePtr->IsImplemented("GevSCPSPacketSize")) - { - // 获取当前网络环境的最优包长值 - int nPacketSize = irisStreamPtr->GetOptimalPacketSize(); - // 将最优包长值设置为当前设备的流通道包长值 - irisFeaturePtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize); - } + m_pobjAcqThread = new CAcquisitionThread(); + m_pobjAcqThread->m_hDevice = m_hDevice; + } + catch (std::bad_alloc &e) + { + QMessageBox::about(NULL, "Allocate memory error", "Cannot allocate memory, please exit this app!"); + RELEASE_ALLOC_MEM(m_pobjAcqThread); + return; } - //设置采集模式为连续采集模式 - irisFeaturePtr->GetEnumFeature("AcquisitionMode")->SetValue("Continuous"); + return; +} - //设置触发模式关 - irisFeaturePtr->GetEnumFeature("TriggerMode")->SetValue("On"); - irisFeaturePtr->GetEnumFeature("TriggerSource")->SetValue("Software"); +void IrisCameraController::UpdateDeviceList() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Enumerate Devcie List + emStatus = GXUpdateDeviceList(&m_ui32DeviceNum, ENUMRATE_TIME_OUT); + + LOG_INFO(QString("[CameraController]枚举虹膜相机成功[%1]").arg(m_ui32DeviceNum).toStdString()); + + return; +} + +void IrisCameraController::StartAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + emStatus = GXStreamOn(m_hDevice); + + // Set acquisition thread run flag + m_pobjAcqThread->m_bAcquisitionThreadFlag = true; + + // Acquisition thread start + m_pobjAcqThread->start(); + + // isStart flag set true + m_bAcquisitionStart = true; + + return; +} + +void IrisCameraController::StopAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Turn off stream + emStatus = GXStreamOff(m_hDevice); + + // isStart flag set false + m_bAcquisitionStart = false; + + return; +} + +bool IrisCameraController::SetAcquisitionBufferNum() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + uint64_t ui64BufferNum = 0; + int64_t i64PayloadSize = 0; + + // Get device current payload size + emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &i64PayloadSize); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Set buffer quantity of acquisition queue + if (i64PayloadSize == 0) + { + return false; + } + + // Calculate a reasonable number of Buffers for different payload size + // Small ROI and high frame rate will requires more acquisition Buffer + const size_t MAX_MEMORY_SIZE = 8 * 1024 * 1024; // The maximum number of memory bytes available for allocating frame Buffer + const size_t MIN_BUFFER_NUM = 5; // Minimum frame Buffer number + const size_t MAX_BUFFER_NUM = 450; // Maximum frame Buffer number + ui64BufferNum = MAX_MEMORY_SIZE / i64PayloadSize; + ui64BufferNum = (ui64BufferNum <= MIN_BUFFER_NUM) ? MIN_BUFFER_NUM : ui64BufferNum; + ui64BufferNum = (ui64BufferNum >= MAX_BUFFER_NUM) ? MAX_BUFFER_NUM : ui64BufferNum; + + emStatus = GXSetAcqusitionBufferNumber(m_hDevice, ui64BufferNum); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Transfer buffer number to acquisition thread class for using GXDQAllBufs + m_pobjAcqThread->m_ui64AcquisitionBufferNum = ui64BufferNum; + + return true; } diff --git a/device/IrisCameraController.h b/device/IrisCameraController.h index 5d7e269..67cbe2f 100644 --- a/device/IrisCameraController.h +++ b/device/IrisCameraController.h @@ -1,11 +1,12 @@ -#ifndef IRISCAMERACONTROLLER_H +#ifndef IRISCAMERACONTROLLER_H #define IRISCAMERACONTROLLER_H #include -#include "IrisCameraCapEventHandler.h" +#include "AcquisitionThread.h" +#include "utils/UtilInclude.h" -class IrisCameraCapEventHandler; +#define ENUMRATE_TIME_OUT 200 class IrisCameraController : public QObject { @@ -14,36 +15,31 @@ explicit IrisCameraController(QObject *parent = nullptr); ~IrisCameraController(); - // 初始化并打开人脸相机 - void initIrisCamera(); void openIrisCamera(); void closeIrisCamera(); void startCapture(); void stopCapture(); - void getLeftAndRightEyeFrame(); + CAcquisitionThread * m_pobjAcqThread; + GX_DEV_HANDLE m_hDevice; ///< Device Handle + uint32_t m_ui32DeviceNum; ///< Device number enumerated - IrisCameraCapEventHandler * irisCamHandler; + bool m_bOpen; ///< Flag : camera is opened or not + bool m_bAcquisitionStart; ///< Flag : camera is acquiring or not private: - GxIAPICPP::gxdeviceinfo_vector irisCamList; - - CGXDevicePointer irisCamPtr; ///< 设备句柄 - - CGXStreamPointer irisStreamPtr; ///< 左眼设备流 - - CGXFeatureControlPointer irisFeaturePtr; ///< 左眼属性控制器 - - CGXFeatureControlPointer irisStreamFeaturePtr; ///< 左眼流层控制器对象 - - void OpenDevice(); + // 初始化并打开人脸相机 + void initIrisCameraController(); + void SetUpAcquisitionThread(); + void UpdateDeviceList(); + bool SetAcquisitionBufferNum(); + void StartAcquisition(); + void StopAcquisition(); signals: - -public slots: - void getOneFaceFrm(); - + void irisCameraInitError(); + void irisCameraTermError(); }; #endif // IRISCAMERACONTROLLER_H diff --git a/device/device.pri b/device/device.pri index d1330a0..583721b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,13 +1,14 @@ HEADERS += $$PWD/IrisCameraController.h -HEADERS += $$PWD/IrisCameraCapEventHandler.h -#HEADERS += $$PWD/iris/IrisRegistProcess.h +#HEADERS += $$PWD/IrisCameraCapEventHandler.h +HEADERS += $$PWD/Common.h +HEADERS += $$PWD/AcquisitionThread.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h SOURCES += $$PWD/IrisCameraController.cpp -SOURCES += $$PWD/IrisCameraCapEventHandler.cpp -#SOURCES += $$PWD/iris/IrisRegistProcess.cpp +#SOURCES += $$PWD/IrisCameraCapEventHandler.cpp +SOURCES += $$PWD/AcquisitionThread.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 38f54fe..e4c8a02 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -11,7 +11,7 @@ // 连接算法服务 clientUtil = new SocketClientUtil(this); - clientUtil->connect("192.168.83.223", 50007); + clientUtil->connect(SettingConfig::getInstance().DEBUG_SEGMENT_IP, 50007); // 调用socket发送消息 connect(this, &IrisRecogProcess::sendDataToExract, clientUtil, &SocketClientUtil::sendData); @@ -43,18 +43,18 @@ continue; } - // 1. 图像栈中没有图像则直接返回 - if (ProMemory::getInstance().isIrisQueueEmpty() == true) + // 1. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 + if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) { - qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); + qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } - // 2. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 - if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) + // 2. 图像栈中没有图像则直接返回 + if (ProMemory::getInstance().isIrisQueueEmpty() == true) { - qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); + qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } @@ -73,7 +73,7 @@ int findEyeLast = timer.elapsed(); qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); -// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.matData = cv::imread("/home/casic/code/irisLogs/145333.552.bmp", 0); // irisInfo.hasEye = true; // 4.1 没有找到眼睛则返回 @@ -117,11 +117,10 @@ // 缩放到320 * 240 cv::resize(segMat, segMat, cv::Size(SettingConfig::getInstance().IRIS_WIDTH * 0.5, SettingConfig::getInstance().IRIS_HEIGHT * 0.5)); - - // std::string filename = QString("%1\\%2\\%3-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - // cv::imwrite(filename, segMat); - // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - +/* + std::string filename = QString("%1/%2/%3-seg.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(filename, segMat); +*/ int segMatSize = segMat.cols * segMat.rows; QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 @@ -167,9 +166,9 @@ // 成功接收后清除缓存区 clientUtil->resetRecvBuffer(); /* - std::string pupilSeg = QString("%1\\%2\\%3-pupil-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string maskSeg = QString("%1\\%2\\%3-mask-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string irisSeg = QString("%1\\%2\\%3-iris-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string pupilSeg = QString("%1/%2/%3-pupil-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); cv::imwrite(pupilSeg, pupil); cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); @@ -196,12 +195,20 @@ CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; irisInfo = casic::iris::CasicIrisInterface::getInstance().irisEncode(irisInfo); /* - std::string codeFilename = QString("%1\\%2\\%3-code.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string codeFilename = QString("%1/%2/%3-code.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string maskFilename = QString("%1/%2/%3-mask.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); */ + if (irisInfo.postProcSucc == false) { + qDebug() << "算法post process失败,暂停200ms"; + + addOneTryCount(); + this->msleep(THREAD_MSLEEP); // 200ms后再判断 + continue; + } + // 从编码中提取特征值 irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); @@ -211,6 +218,8 @@ CasicIrisRecState::getInstance().extractTmLast = encodeLast; CasicIrisRecState::getInstance().recogTimeLast += encodeLast; +// cv::imwrite(QString("%1/%2/%3.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(), irisInfo.matData); + // 开始匹配 timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) @@ -219,7 +228,7 @@ float score = casic::iris::CasicIrisInterface::getInstance().calculatePairPoints(feature.irisFeatureCode, irisInfo.irisFeatureCode); // 计算压缩编码的比较值 -// cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); +// cv::imwrite(QString("%1/%2/%3-%4.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; @@ -251,7 +260,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } @@ -268,7 +277,7 @@ CasicIrisRecState::getInstance().tryCount = 0; this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); emit failedMatchedIris(); @@ -290,7 +299,7 @@ // 识别失败时暂停工作 待返回识别界面时再开始工作和拍图 this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); } } else if (ProMemory::getInstance().appState == AppConstants::ApplicationState::STATE_WORKING) @@ -298,7 +307,8 @@ CasicIrisRecState::getInstance().noEyeCount++; // 如果在工作状态 则超过一定次数后返回待机 - if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT) + if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT && + SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT > 0) { // 发送信号待机 emit backToLockScreen(); diff --git a/device/iris/IrisRecogProcess.h b/device/iris/IrisRecogProcess.h index 9a3eec6..e21c1a7 100644 --- a/device/iris/IrisRecogProcess.h +++ b/device/iris/IrisRecogProcess.h @@ -1,4 +1,4 @@ -#ifndef IRISRECOGPROCESS_H +#ifndef IRISRECOGPROCESS_H #define IRISRECOGPROCESS_H #define THREAD_MSLEEP 200 @@ -10,6 +10,7 @@ #include "ProMemory.h" #include "device/iris/CasicIrisRecState.h" +#include "casic/iris/CasicIrisInterface.h" class IrisRecogProcess : public QThread { diff --git a/main.cpp b/main.cpp index 9052ddb..3bfb1c6 100644 --- a/main.cpp +++ b/main.cpp @@ -1,11 +1,11 @@ -#include "MainWindowForm.h" - -#include - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - MainWindowForm w; - w.show(); - return a.exec(); -} +#include "MainWindowForm.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindowForm w; + w.show(); + return a.exec(); +} diff --git a/utils/ImageUtil.cpp b/utils/ImageUtil.cpp index ff77331..d40ea79 100644 --- a/utils/ImageUtil.cpp +++ b/utils/ImageUtil.cpp @@ -1,107 +1,107 @@ -#include "ImageUtil.h" - -ImageUtil::ImageUtil() -{ - -} - -QImage ImageUtil::MatImageToQImage(const cv::Mat &src) -{ - //CV_8UC1 8位无符号的单通道---灰度图片 - if(src.type() == CV_8UC1) - { - QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); - return qImage; - } - //为3通道的彩色图片 - else if(src.type() == CV_8UC3) - { - //得到图像的的首地址 - const uchar *pSrc = (const uchar*)src.data; - //以src构造图片 - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); - } - //四通道图片, 带Alpha通道的RGB彩色图像 - else if(src.type() == CV_8UC4) - { - const uchar *pSrc = (const uchar*)src.data; - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); - //返回图像的子区域作为一个新图像 - return qImage.copy(); - } - else - { - return QImage(); - } -} - -cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) -{ - cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); - return img; -} - -cv::Mat ImageUtil::QImageToMat(QImage image) -{ - cv::Mat mat; - switch(image.format()) - { - case QImage::Format_ARGB32: - case QImage::Format_RGB32: - case QImage::Format_ARGB32_Premultiplied: - mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_RGB888: - mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); - cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); - break; - case QImage::Format_Indexed8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_Grayscale8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); - break; - - default: - break; - } - - mat = mat.clone(); - - return mat; -} - -/* -QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) -{ - QImage qImage(data, width, height, format); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); -} - -QString ImageUtil::QImageToBase64(QImage image) -{ - QByteArray ba; - QBuffer buf(&ba); - image.save(&buf, "bmp"); - QString base64String = ba.toBase64(); - return base64String; -} - -cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) -{ - cv::Mat matClone = src.clone(); - cv::Rect bigRect; - - bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; - bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; - bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; - bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; - - cv::Mat roi = matClone(bigRect); - - return roi; -} -*/ +#include "ImageUtil.h" + +ImageUtil::ImageUtil() +{ + +} + +QImage ImageUtil::MatImageToQImage(const cv::Mat &src) +{ + //CV_8UC1 8位无符号的单通道---灰度图片 + if(src.type() == CV_8UC1) + { + QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); + return qImage; + } + //为3通道的彩色图片 + else if(src.type() == CV_8UC3) + { + //得到图像的的首地址 + const uchar *pSrc = (const uchar*)src.data; + //以src构造图片 + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); + } + //四通道图片, 带Alpha通道的RGB彩色图像 + else if(src.type() == CV_8UC4) + { + const uchar *pSrc = (const uchar*)src.data; + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); + //返回图像的子区域作为一个新图像 + return qImage.copy(); + } + else + { + return QImage(); + } +} + +cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) +{ + cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); + return img; +} + +cv::Mat ImageUtil::QImageToMat(QImage image) +{ + cv::Mat mat; + switch(image.format()) + { + case QImage::Format_ARGB32: + case QImage::Format_RGB32: + case QImage::Format_ARGB32_Premultiplied: + mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_RGB888: + mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); + cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); + break; + case QImage::Format_Indexed8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_Grayscale8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); + break; + + default: + break; + } + + mat = mat.clone(); + + return mat; +} + +/* +QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) +{ + QImage qImage(data, width, height, format); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); +} + +QString ImageUtil::QImageToBase64(QImage image) +{ + QByteArray ba; + QBuffer buf(&ba); + image.save(&buf, "bmp"); + QString base64String = ba.toBase64(); + return base64String; +} + +cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) +{ + cv::Mat matClone = src.clone(); + cv::Rect bigRect; + + bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; + bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; + bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; + bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; + + cv::Mat roi = matClone(bigRect); + + return roi; +} +*/ diff --git a/utils/ImageUtil.h b/utils/ImageUtil.h index d9bf00a..4b702f4 100644 --- a/utils/ImageUtil.h +++ b/utils/ImageUtil.h @@ -1,23 +1,23 @@ -#ifndef IMAGEUTIL_H -#define IMAGEUTIL_H - -#include -#include -#include "opencv2/opencv.hpp" - -class ImageUtil -{ -public: - ImageUtil(); - - static QImage MatImageToQImage(const cv::Mat &src); -// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); - - static cv::Mat ucharToMat(unsigned char * data, int row, int col); - static cv::Mat QImageToMat(QImage image); -// static QString QImageToBase64(QImage image); - -// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); -}; - -#endif // IMAGEUTIL_H +#ifndef IMAGEUTIL_H +#define IMAGEUTIL_H + +#include +#include +#include "opencv2/opencv.hpp" + +class ImageUtil +{ +public: + ImageUtil(); + + static QImage MatImageToQImage(const cv::Mat &src); +// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); + + static cv::Mat ucharToMat(unsigned char * data, int row, int col); + static cv::Mat QImageToMat(QImage image); +// static QString QImageToBase64(QImage image); + +// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); +}; + +#endif // IMAGEUTIL_H diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp index 663db0f..05c4c68 100644 --- a/utils/SettingConfig.cpp +++ b/utils/SettingConfig.cpp @@ -1,4 +1,4 @@ -#include "SettingConfig.h" +#include "SettingConfig.h" #include SettingConfig::SettingConfig() @@ -34,6 +34,9 @@ LOG_FILE = getProperty("log", "logFile").toString(); LOG_LEVEL = getProperty("log", "logLevel").toString(); + + DEBUG_CAMERA_ROTATE = getProperty("debug", "cameraRotate").toString(); + DEBUG_SEGMENT_IP = getProperty("debug", "segmentIp").toString(); } diff --git a/utils/SettingConfig.h b/utils/SettingConfig.h index b65f553..c35d6ab 100644 --- a/utils/SettingConfig.h +++ b/utils/SettingConfig.h @@ -1,4 +1,4 @@ -#ifndef SETTINGCONFIG_H +#ifndef SETTINGCONFIG_H #define SETTINGCONFIG_H #include @@ -55,6 +55,9 @@ QString LOG_FILE; QString LOG_LEVEL; + QString DEBUG_CAMERA_ROTATE; + QString DEBUG_SEGMENT_IP; + private: SettingConfig(); diff --git a/utils/SocketClientUtil.cpp b/utils/SocketClientUtil.cpp index d539d64..20b8869 100644 --- a/utils/SocketClientUtil.cpp +++ b/utils/SocketClientUtil.cpp @@ -1,9 +1,10 @@ -#include "SocketClientUtil.h" +#include "SocketClientUtil.h" #include "utils/ByteUtil.h" SocketClientUtil::SocketClientUtil(QObject *parent) : QObject(parent) { QObject::connect(&objClient, &QTcpSocket::readyRead, this, &SocketClientUtil::readData); + QObject::connect(&objClient, &QTcpSocket::disconnected, this, &SocketClientUtil::socketReconnect); } void SocketClientUtil::connect(QString host, int port) @@ -16,6 +17,10 @@ void SocketClientUtil::closeConnect() { + QObject::disconnect(&objClient, &QTcpSocket::readyRead, this, &SocketClientUtil::readData); + QObject::disconnect(&objClient, &QTcpSocket::disconnected, this, &SocketClientUtil::socketReconnect); + + objClient.disconnectFromHost(); objClient.close(); } @@ -45,3 +50,9 @@ emit this->responseReaded(); } } + +void SocketClientUtil::socketReconnect() +{ + objClient.close(); + objClient.connectToHost(this->host, this->port); +} diff --git a/utils/SocketClientUtil.h b/utils/SocketClientUtil.h index 96b60e0..8bd1b8c 100644 --- a/utils/SocketClientUtil.h +++ b/utils/SocketClientUtil.h @@ -1,4 +1,4 @@ -#ifndef SOCKETCLIENTUTIL_H +#ifndef SOCKETCLIENTUTIL_H #define SOCKETCLIENTUTIL_H #include @@ -30,6 +30,7 @@ public slots: void readData(); void sendData(QByteArray data); + void socketReconnect(); }; diff --git a/utils/TimeCounterUtil.cpp b/utils/TimeCounterUtil.cpp index 275945f..78c3d69 100644 --- a/utils/TimeCounterUtil.cpp +++ b/utils/TimeCounterUtil.cpp @@ -1,8 +1,9 @@ -#include "TimeCounterUtil.h" - -TimeCounterUtil::TimeCounterUtil() -{ - faceCapCounter = new QTimer(); - irisCapCounter = new QTimer(); - clockCounter = new QTimer(); -} +#include "TimeCounterUtil.h" + +TimeCounterUtil::TimeCounterUtil() +{ + faceCapCounter = new QTimer(); + irisCapCounter = new QTimer(); + clockCounter = new QTimer(); + videoCounter = new QTimer(); +} diff --git a/utils/TimeCounterUtil.h b/utils/TimeCounterUtil.h index 28b29f1..91f8da0 100644 --- a/utils/TimeCounterUtil.h +++ b/utils/TimeCounterUtil.h @@ -1,29 +1,30 @@ -#ifndef TIMECOUNTERUTIL_H -#define TIMECOUNTERUTIL_H - -#include -#include - -class TimeCounterUtil : public QObject -{ -public: - - ~TimeCounterUtil() {}; - TimeCounterUtil(const TimeCounterUtil&)=delete; - TimeCounterUtil& operator=(const TimeCounterUtil&)=delete; - - static TimeCounterUtil& getInstance() { - static TimeCounterUtil instance; - return instance; - } - - QTimer * faceCapCounter; - QTimer * irisCapCounter; - QTimer * clockCounter; - -private: - TimeCounterUtil(); - -}; - -#endif // TIMECOUNTERUTIL_H +#ifndef TIMECOUNTERUTIL_H +#define TIMECOUNTERUTIL_H + +#include +#include + +class TimeCounterUtil : public QObject +{ +public: + + ~TimeCounterUtil() {}; + TimeCounterUtil(const TimeCounterUtil&)=delete; + TimeCounterUtil& operator=(const TimeCounterUtil&)=delete; + + static TimeCounterUtil& getInstance() { + static TimeCounterUtil instance; + return instance; + } + + QTimer * faceCapCounter; + QTimer * irisCapCounter; + QTimer * clockCounter; + QTimer * videoCounter; // show video images on main window + +private: + TimeCounterUtil(); + +}; + +#endif // TIMECOUNTERUTIL_H diff --git a/utils/UtilInclude.h b/utils/UtilInclude.h index 0b329c9..bea17be 100644 --- a/utils/UtilInclude.h +++ b/utils/UtilInclude.h @@ -1,15 +1,15 @@ -#ifndef UTILINCLUDE_H -#define UTILINCLUDE_H - -#include -#include "ByteUtil.h" -#include "ImageUtil.h" -#include "LogUtil.h" -#include "SettingConfig.h" -#include "SocketClientUtil.h" -#include "SpeakerUtil.h" -#include "TimeCounterUtil.h" -//#include "UDPClientUtil.h" -//#include "HttpRequestUtil.h" - -#endif // UTILINCLUDE_H +#ifndef UTILINCLUDE_H +#define UTILINCLUDE_H + +#include +#include "ByteUtil.h" +#include "ImageUtil.h" +#include "LogUtil.h" +#include "SettingConfig.h" +#include "SocketClientUtil.h" +#include "SpeakerUtil.h" +#include "TimeCounterUtil.h" +//#include "UDPClientUtil.h" +//#include "HttpRequestUtil.h" + +#endif // UTILINCLUDE_H diff --git a/utils/id/IdWorker.h b/utils/id/IdWorker.h index 6c48aa9..079bbcb 100644 --- a/utils/id/IdWorker.h +++ b/utils/id/IdWorker.h @@ -1,218 +1,218 @@ -#ifndef _JW_CORE_ID_WORKER_H_ -#define _JW_CORE_ID_WORKER_H_ - -#include -#include -#include -#include -#include -#include "Noncopyable.h" -#include "Singleton.h" - -// 如果不使用 mutex, 则开启下面这个定义, 但是我发现, 还是开启 mutex 功能, 速度比较快 -// #define SNOWFLAKE_ID_WORKER_NO_LOCK - -namespace Jiawa { - - /** - * @brief 核心 - * 核心功能 - */ - namespace Core { - - /** - * @brief 分布式id生成类 - * https://segmentfault.com/a/1190000011282426 - * https://github.com/twitter/snowflake/blob/snowflake-2010/src/main/scala/com/twitter/service/snowflake/IdWorker.scala - * - * 64bit id: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 - * || || || | | | - * |└---------------------------时间戳--------------------------┘└中心-┘└机器-┘ └----序列号----┘ - * | - * 不用 - * SnowFlake的优点: 整体上按照时间自增排序, 并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分), 并且效率较高, 经测试, SnowFlake每秒能够产生26万ID左右. - */ - class SnowflakeIdWorker : private Noncopyable { - - // 实现单例 - friend class Singleton; - - public: - typedef unsigned int UInt; - typedef unsigned long long int UInt64; - -#ifdef SNOWFLAKE_ID_WORKER_NO_LOCK - typedef std::atomic AtomicUInt; - typedef std::atomic AtomicUInt64; -#else - typedef UInt AtomicUInt; - typedef UInt64 AtomicUInt64; -#endif - - void setWorkerId(UInt workerId) { - this->workerId = workerId; - } - - void setDatacenterId(UInt datacenterId) { - this->datacenterId = datacenterId; - } - - UInt64 getId() { - return nextId(); - } - - /** - * 获得下一个ID (该方法是线程安全的) - * - * @return SnowflakeId - */ - UInt64 nextId() { -#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK - std::unique_lock lock{ mutex }; - AtomicUInt64 timestamp{ 0 }; -#else - static AtomicUInt64 timestamp{ 0 }; -#endif - timestamp = timeGen(); - - // 如果当前时间小于上一次ID生成的时间戳, 说明系统时钟回退过这个时候应当抛出异常 - if (timestamp < lastTimestamp) { - std::ostringstream s; - s << "clock moved backwards. Refusing to generate id for " << lastTimestamp - timestamp << " milliseconds"; - throw std::exception(std::runtime_error(s.str())); - } - - if (lastTimestamp == timestamp) { - // 如果是同一时间生成的, 则进行毫秒内序列 - sequence = (sequence + 1) & sequenceMask; - if (0 == sequence) { - // 毫秒内序列溢出, 阻塞到下一个毫秒,获得新的时间戳 - timestamp = tilNextMillis(lastTimestamp); - } - } else { - sequence = 0; - } - -#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK - lastTimestamp = timestamp; -#else - lastTimestamp = timestamp.load(); -#endif - - // 移位并通过或运算拼到一起组成64位的ID - return ((timestamp - twepoch) << timestampLeftShift) - | (datacenterId << datacenterIdShift) - | (workerId << workerIdShift) - | sequence; - } - - protected: - SnowflakeIdWorker() : workerId(0), datacenterId(0), sequence(0), lastTimestamp(0) { } - - /** - * 返回以毫秒为单位的当前时间 - * - * @return 当前时间(毫秒) - */ - UInt64 timeGen() const { - auto t = std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()); - return t.time_since_epoch().count(); - } - - /** - * 阻塞到下一个毫秒, 直到获得新的时间戳 - * - * @param lastTimestamp 上次生成ID的时间截 - * @return 当前时间戳 - */ - UInt64 tilNextMillis(UInt64 lastTimestamp) const { - UInt64 timestamp = timeGen(); - while (timestamp <= lastTimestamp) { - timestamp = timeGen(); - } - return timestamp; - } - - private: - -#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK - std::mutex mutex; -#endif - - /** - * 开始时间截 (2018-01-01 00:00:00.000) - */ - const UInt64 twepoch = 1514736000000; - - /** - * 机器id所占的位数 - */ - const UInt workerIdBits = 5; - - /** - * 数据中心id所占的位数 - */ - const UInt datacenterIdBits = 5; - - /** - * 序列所占的位数 - */ - const UInt sequenceBits = 12; - - /** - * 机器ID向左移12位 - */ - const UInt workerIdShift = sequenceBits; - - /** - * 数据标识id向左移17位 - */ - const UInt datacenterIdShift = workerIdShift + workerIdBits; - - /** - * 时间截向左移22位 - */ - const UInt timestampLeftShift = datacenterIdShift + datacenterIdBits; - - /** - * 支持的最大机器id, 结果是31 - */ - const UInt maxWorkerId = -1 ^ (-1 << workerIdBits); - - /** - * 支持的最大数据中心id, 结果是31 - */ - const UInt maxDatacenterId = -1 ^ (-1 << datacenterIdBits); - - /** - * 生成序列的掩码, 这里为4095 - */ - const UInt sequenceMask = -1 ^ (-1 << sequenceBits); - - /** - * 工作机器id(0~31) - */ - UInt workerId; - - /** - * 数据中心id(0~31) - */ - UInt datacenterId; - - /** - * 毫秒内序列(0~4095) - */ - AtomicUInt sequence{ 0 }; - - /** - * 上次生成ID的时间截 - */ - AtomicUInt64 lastTimestamp{ 0 }; - - }; - - typedef SnowflakeIdWorker IdWorker; - } -} - -#endif // _JW_CORE_ID_WORKER_H_ +#ifndef _JW_CORE_ID_WORKER_H_ +#define _JW_CORE_ID_WORKER_H_ + +#include +#include +#include +#include +#include +#include "Noncopyable.h" +#include "Singleton.h" + +// 如果不使用 mutex, 则开启下面这个定义, 但是我发现, 还是开启 mutex 功能, 速度比较快 +// #define SNOWFLAKE_ID_WORKER_NO_LOCK + +namespace Jiawa { + + /** + * @brief 核心 + * 核心功能 + */ + namespace Core { + + /** + * @brief 分布式id生成类 + * https://segmentfault.com/a/1190000011282426 + * https://github.com/twitter/snowflake/blob/snowflake-2010/src/main/scala/com/twitter/service/snowflake/IdWorker.scala + * + * 64bit id: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + * || || || | | | + * |└---------------------------时间戳--------------------------┘└中心-┘└机器-┘ └----序列号----┘ + * | + * 不用 + * SnowFlake的优点: 整体上按照时间自增排序, 并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分), 并且效率较高, 经测试, SnowFlake每秒能够产生26万ID左右. + */ + class SnowflakeIdWorker : private Noncopyable { + + // 实现单例 + friend class Singleton; + + public: + typedef unsigned int UInt; + typedef unsigned long long int UInt64; + +#ifdef SNOWFLAKE_ID_WORKER_NO_LOCK + typedef std::atomic AtomicUInt; + typedef std::atomic AtomicUInt64; +#else + typedef UInt AtomicUInt; + typedef UInt64 AtomicUInt64; +#endif + + void setWorkerId(UInt workerId) { + this->workerId = workerId; + } + + void setDatacenterId(UInt datacenterId) { + this->datacenterId = datacenterId; + } + + UInt64 getId() { + return nextId(); + } + + /** + * 获得下一个ID (该方法是线程安全的) + * + * @return SnowflakeId + */ + UInt64 nextId() { +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + std::unique_lock lock{ mutex }; + AtomicUInt64 timestamp{ 0 }; +#else + static AtomicUInt64 timestamp{ 0 }; +#endif + timestamp = timeGen(); + + // 如果当前时间小于上一次ID生成的时间戳, 说明系统时钟回退过这个时候应当抛出异常 + if (timestamp < lastTimestamp) { + std::ostringstream s; + s << "clock moved backwards. Refusing to generate id for " << lastTimestamp - timestamp << " milliseconds"; + throw std::exception(std::runtime_error(s.str())); + } + + if (lastTimestamp == timestamp) { + // 如果是同一时间生成的, 则进行毫秒内序列 + sequence = (sequence + 1) & sequenceMask; + if (0 == sequence) { + // 毫秒内序列溢出, 阻塞到下一个毫秒,获得新的时间戳 + timestamp = tilNextMillis(lastTimestamp); + } + } else { + sequence = 0; + } + +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + lastTimestamp = timestamp; +#else + lastTimestamp = timestamp.load(); +#endif + + // 移位并通过或运算拼到一起组成64位的ID + return ((timestamp - twepoch) << timestampLeftShift) + | (datacenterId << datacenterIdShift) + | (workerId << workerIdShift) + | sequence; + } + + protected: + SnowflakeIdWorker() : workerId(0), datacenterId(0), sequence(0), lastTimestamp(0) { } + + /** + * 返回以毫秒为单位的当前时间 + * + * @return 当前时间(毫秒) + */ + UInt64 timeGen() const { + auto t = std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()); + return t.time_since_epoch().count(); + } + + /** + * 阻塞到下一个毫秒, 直到获得新的时间戳 + * + * @param lastTimestamp 上次生成ID的时间截 + * @return 当前时间戳 + */ + UInt64 tilNextMillis(UInt64 lastTimestamp) const { + UInt64 timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + private: + +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + std::mutex mutex; +#endif + + /** + * 开始时间截 (2018-01-01 00:00:00.000) + */ + const UInt64 twepoch = 1514736000000; + + /** + * 机器id所占的位数 + */ + const UInt workerIdBits = 5; + + /** + * 数据中心id所占的位数 + */ + const UInt datacenterIdBits = 5; + + /** + * 序列所占的位数 + */ + const UInt sequenceBits = 12; + + /** + * 机器ID向左移12位 + */ + const UInt workerIdShift = sequenceBits; + + /** + * 数据标识id向左移17位 + */ + const UInt datacenterIdShift = workerIdShift + workerIdBits; + + /** + * 时间截向左移22位 + */ + const UInt timestampLeftShift = datacenterIdShift + datacenterIdBits; + + /** + * 支持的最大机器id, 结果是31 + */ + const UInt maxWorkerId = -1 ^ (-1 << workerIdBits); + + /** + * 支持的最大数据中心id, 结果是31 + */ + const UInt maxDatacenterId = -1 ^ (-1 << datacenterIdBits); + + /** + * 生成序列的掩码, 这里为4095 + */ + const UInt sequenceMask = -1 ^ (-1 << sequenceBits); + + /** + * 工作机器id(0~31) + */ + UInt workerId; + + /** + * 数据中心id(0~31) + */ + UInt datacenterId; + + /** + * 毫秒内序列(0~4095) + */ + AtomicUInt sequence{ 0 }; + + /** + * 上次生成ID的时间截 + */ + AtomicUInt64 lastTimestamp{ 0 }; + + }; + + typedef SnowflakeIdWorker IdWorker; + } +} + +#endif // _JW_CORE_ID_WORKER_H_ diff --git a/utils/id/Noncopyable.h b/utils/id/Noncopyable.h index d87f58a..4fc555a 100644 --- a/utils/id/Noncopyable.h +++ b/utils/id/Noncopyable.h @@ -1,31 +1,31 @@ -#ifndef _JW_CORE_NONCOPYABLE_H_ -#define _JW_CORE_NONCOPYABLE_H_ - - -// Private copy constructor and copy assignment ensure classes derived from -// class noncopyable cannot be copied. - -namespace Jiawa { - namespace Core { - - // protection from unintended ADL(Argument Dependent Lookup) - namespace Noncopyable_ { - - class Noncopyable - { - protected: - Noncopyable() = default; - ~Noncopyable() = default; - - Noncopyable(const Noncopyable&) = delete; - Noncopyable(const Noncopyable&&) = delete; - Noncopyable& operator=(const Noncopyable&) = delete; - Noncopyable& operator=(const Noncopyable&&) = delete; - }; - } - - typedef Noncopyable_::Noncopyable Noncopyable; - } -} - -#endif // _JW_CORE_NONCOPYABLE_H_ +#ifndef _JW_CORE_NONCOPYABLE_H_ +#define _JW_CORE_NONCOPYABLE_H_ + + +// Private copy constructor and copy assignment ensure classes derived from +// class noncopyable cannot be copied. + +namespace Jiawa { + namespace Core { + + // protection from unintended ADL(Argument Dependent Lookup) + namespace Noncopyable_ { + + class Noncopyable + { + protected: + Noncopyable() = default; + ~Noncopyable() = default; + + Noncopyable(const Noncopyable&) = delete; + Noncopyable(const Noncopyable&&) = delete; + Noncopyable& operator=(const Noncopyable&) = delete; + Noncopyable& operator=(const Noncopyable&&) = delete; + }; + } + + typedef Noncopyable_::Noncopyable Noncopyable; + } +} + +#endif // _JW_CORE_NONCOPYABLE_H_ diff --git a/utils/id/Singleton.h b/utils/id/Singleton.h index d1c0553..daad45c 100644 --- a/utils/id/Singleton.h +++ b/utils/id/Singleton.h @@ -1,60 +1,60 @@ -#ifndef _JW_CORE_SINGLETON_H_ -#define _JW_CORE_SINGLETON_H_ - -namespace Jiawa { - namespace Core { - - // boost/container/detail/singleton.hpp - // http://blog.csdn.net/fullsail/article/details/8483106 - // T must be: no-throw default constructible and no-throw destructible - template - class Singleton { - private: - Singleton() = default; - ~Singleton() = default; - - private: - struct object_creator - { - // This constructor does nothing more than ensure that instance() - // is called before main() begins, thus creating the static - // T object before multithreading race issues can come up. - object_creator() { Singleton::instance(); } - inline void do_nothing() const { } - }; - static object_creator create_object; - - private: - Singleton(const Singleton&) = delete; - Singleton(const Singleton&&) = delete; - Singleton& operator=(const Singleton&) = delete; - Singleton& operator=(const Singleton&&) = delete; - - public: - typedef T object_type; - - // If, at any point (in user code), Singleton::instance() - // is called, then the following function is instantiated. - static object_type& instance() - { - // This is the object that we return a reference to. - // It is guaranteed to be created before main() begins because of - // the next line. - static object_type obj; - - // The following line does nothing else than force the instantiation - // of Singleton::create_object, whose constructor is - // called before main() begins. - create_object.do_nothing(); - - return obj; - } - }; - - template - typename Singleton::object_creator Singleton::create_object; - } -} - -#endif // _JW_CORE_SINGLETON_H_ - +#ifndef _JW_CORE_SINGLETON_H_ +#define _JW_CORE_SINGLETON_H_ + +namespace Jiawa { + namespace Core { + + // boost/container/detail/singleton.hpp + // http://blog.csdn.net/fullsail/article/details/8483106 + // T must be: no-throw default constructible and no-throw destructible + template + class Singleton { + private: + Singleton() = default; + ~Singleton() = default; + + private: + struct object_creator + { + // This constructor does nothing more than ensure that instance() + // is called before main() begins, thus creating the static + // T object before multithreading race issues can come up. + object_creator() { Singleton::instance(); } + inline void do_nothing() const { } + }; + static object_creator create_object; + + private: + Singleton(const Singleton&) = delete; + Singleton(const Singleton&&) = delete; + Singleton& operator=(const Singleton&) = delete; + Singleton& operator=(const Singleton&&) = delete; + + public: + typedef T object_type; + + // If, at any point (in user code), Singleton::instance() + // is called, then the following function is instantiated. + static object_type& instance() + { + // This is the object that we return a reference to. + // It is guaranteed to be created before main() begins because of + // the next line. + static object_type obj; + + // The following line does nothing else than force the instantiation + // of Singleton::create_object, whose constructor is + // called before main() begins. + create_object.do_nothing(); + + return obj; + } + }; + + template + typename Singleton::object_creator Singleton::create_object; + } +} + +#endif // _JW_CORE_SINGLETON_H_ + diff --git a/utils/id/Timer.h b/utils/id/Timer.h index 0f1ff1b..4b2967f 100644 --- a/utils/id/Timer.h +++ b/utils/id/Timer.h @@ -1,57 +1,57 @@ -#ifndef _JW_CORE_TIMER_H_ -#define _JW_CORE_TIMER_H_ - -#include - -namespace Jiawa { - - /** - * @brief 核心 - * 核心功能 - */ - namespace Core { - - /** - * @brief 计时器类 - * 计时 - */ - template - class Timer { - public: - - typedef CLOCK clock; - typedef typename CLOCK::rep rep; - typedef typename CLOCK::duration duration; - typedef typename CLOCK::time_point time_point; - - Timer() : m_start(CLOCK::now()) { - } - - /** - * @brief 重置计时器 - * - * @return 开始的时间点 - */ - time_point reset() { - m_start = CLOCK::now(); - return m_start; - } - - /** - * @brief 得到流逝的时间 - * @param UNIT 返回时间的类型 - * - * @return 返回流逝的时间 - */ - template - typename UNIT::duration::rep elapsed() const { - return std::chrono::duration_cast(CLOCK::now() - m_start).count(); - } - - private: - time_point m_start; - }; - } -} - +#ifndef _JW_CORE_TIMER_H_ +#define _JW_CORE_TIMER_H_ + +#include + +namespace Jiawa { + + /** + * @brief 核心 + * 核心功能 + */ + namespace Core { + + /** + * @brief 计时器类 + * 计时 + */ + template + class Timer { + public: + + typedef CLOCK clock; + typedef typename CLOCK::rep rep; + typedef typename CLOCK::duration duration; + typedef typename CLOCK::time_point time_point; + + Timer() : m_start(CLOCK::now()) { + } + + /** + * @brief 重置计时器 + * + * @return 开始的时间点 + */ + time_point reset() { + m_start = CLOCK::now(); + return m_start; + } + + /** + * @brief 得到流逝的时间 + * @param UNIT 返回时间的类型 + * + * @return 返回流逝的时间 + */ + template + typename UNIT::duration::rep elapsed() const { + return std::chrono::duration_cast(CLOCK::now() - m_start).count(); + } + + private: + time_point m_start; + }; + } +} + #endif // _JW_CORE_TIMER_H_ \ No newline at end of file diff --git a/.gitignore b/.gitignore index fab7372..1358d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,73 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro index da314a4..c31991e 100644 --- a/CasicIrisIdentify.pro +++ b/CasicIrisIdentify.pro @@ -1,62 +1,59 @@ -QT += core gui sql network texttospeech - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include("casic/casic.pri") -include("dao/dao.pri") -include("device/device.pri") -include("utils/utils.pri") - -SOURCES += main.cpp -SOURCES += ProMemory.cpp -SOURCES += MainWindowForm.cpp -SOURCES += IdentifyForm.cpp -SOURCES += LockScreenForm.cpp - -HEADERS += AppConstants.h -HEADERS += ProMemory.h -HEADERS += MainWindowForm.h -HEADERS += IdentifyForm.h -HEADERS += LockScreenForm.h - -FORMS += MainWindowForm.ui -FORMS += IdentifyForm.ui -FORMS += LockScreenForm.ui - -RESOURCES += resource.qrc - -DISTFILES += conf/config.ini - -#INCLUDEPATH += include/spdlog -#DEPENDPATH += include/spdlog - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420 -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lopencv_world420d -else:unix:!macx: LIBS += -L$$PWD/lib/ -lopencv_world420 -unix:!macx|win32: LIBS += -L$$PWD/lib/ -lGxIAPICPPEx - -INCLUDEPATH += $$PWD/include/daheng -DEPENDPATH += $$PWD/include/daheng - -INCLUDEPATH += $$PWD/include -DEPENDPATH += $$PWD/include - -INCLUDEPATH += $$PWD/Eigen +QT += core gui sql network texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include("casic/casic.pri") +include("dao/dao.pri") +include("device/device.pri") +include("utils/utils.pri") + +SOURCES += main.cpp +SOURCES += ProMemory.cpp +SOURCES += MainWindowForm.cpp +SOURCES += IdentifyForm.cpp +SOURCES += LockScreenForm.cpp + +HEADERS += AppConstants.h +HEADERS += ProMemory.h +HEADERS += MainWindowForm.h +HEADERS += IdentifyForm.h +HEADERS += LockScreenForm.h + +FORMS += MainWindowForm.ui +FORMS += IdentifyForm.ui +FORMS += LockScreenForm.ui + +RESOURCES += resource.qrc + +DISTFILES += conf/config.ini + +#INCLUDEPATH += include/spdlog +#DEPENDPATH += include/spdlog + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/Eigen + +unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi + +INCLUDEPATH += $$PWD/include/daheng +DEPENDPATH += $$PWD/include/daheng + +LIBS += $(shell pkg-config opencv4 --libs) +INCLUDEPATH += /usr/include/opencv4 diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 48dee69..8548ecd 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -1,122 +1,161 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "IdentifyForm.h" -#include "ui_IdentifyForm.h" - -IdentifyForm::IdentifyForm(QWidget *parent) - : QWidget(parent) - , ui(new Ui::IdentifyForm) -{ - ui->setupUi(this); - - ui->wgtIdentifying->setCurrentIndex(0); - - ui->labelIdenTips->setText(""); - ui->labelFailTips->setText("识 别 失 败\n请 重 试"); -} - -IdentifyForm::~IdentifyForm() -{ - delete ui; -} - -void IdentifyForm::updateIdentifyTips(QString tips) -{ - ui->labelIdenTips->setText(tips); -} - -void IdentifyForm::drawIrisImageOnFrame(QImage image) -{ - // 只在识别界面才显示画面 - if (ui->wgtIdentifying->currentIndex() == 0) { - ui->labelVideo->setPixmap(QPixmap::fromImage(image)); - } -} - -void IdentifyForm::showRecogFailure() -{ - SpeakerUtil::getInstance().speak("识别失败,请重试"); - - ui->wgtIdentifying->setCurrentIndex(2); - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} - -void IdentifyForm::showRecognizeResult(QString personId) -{ - QVariantMap matched = personDao.findRecordById(personId); - - QString deptName = matched.value("deptname").toString(); - QString personName = matched.value("name").toString(); - SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); - - ui->wgtIdentifying->setCurrentIndex(1); - - // 查询并显示人员信息 - ui->labelName->setText(""); - ui->labelName->setText(personName); - ui->labelGender->setText(""); - ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); - ui->labelDept->setText(""); - ui->labelDept->setText(deptName); - ui->labelTs->setText(""); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - - // 查询并显示头像 - QPixmap photo; - QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); - bool succ = photo.load(photoPath); - if (succ == false) { - photo.load(":/images/photo.png"); - } - - // 缩放到合适的尺寸 - float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 - - if (rp <= rl) { - // 如果图片的比例小则缩放到显示框的高度 - photo = photo.scaledToHeight(ui->labelPhoto->height()); - } else { - // 如果图片的比例大则缩放到显示框的宽度 - photo = photo.scaledToWidth(ui->labelPhoto->width()); - } - // 显示 - ui->labelPhoto->setPixmap(photo); - - // 执行数据库操作 - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; - record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); - record.insert("debug_info", CasicIrisRecState::getInstance().toString()); - recordDao.save(record); - - // 返回工作状态和界面 - QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ - ProMemory::getInstance().irisCam->startCapture(); - ProMemory::getInstance().irisRecogPro->setWorking(true); - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; - ui->labelIdenTips->setText(""); - - // 清除上一次识别的状态信息 - CasicIrisRecState::getInstance().restRecognize(); - ui->wgtIdentifying->setCurrentIndex(0); - }); -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "IdentifyForm.h" +#include "ui_IdentifyForm.h" + +IdentifyForm::IdentifyForm(QWidget *parent) + : QWidget(parent) + , ui(new Ui::IdentifyForm) +{ + ui->setupUi(this); + + ui->wgtIdentifying->setCurrentIndex(0); + + ui->labelIdenTips->setText(""); + ui->labelFailTips->setText("识 别 失 败\n请 重 试"); +} + +IdentifyForm::~IdentifyForm() +{ + delete ui; +} + +void IdentifyForm::updateIdentifyTips(QString tips) +{ + ui->labelIdenTips->setText(tips); +} + +void IdentifyForm::drawIrisImageOnFrame() +{ + // If acquisition did not started + if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart) + { + return; + } + + // Get Image from image show queue, if image show queue is empty, return directly + QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque(); + if(qobjImgShow == NULL) + { + return; + } + + QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8); + + // 图像逆时针旋转90度 + objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt())); + + // 创建虹膜信息对象 + CasicIrisInfo irisInfo; + irisInfo.hasEye = false; + irisInfo.postProcSucc = false; + + // 存入图像栈 + cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray); + irisInfo.matData = irisMat; + + ProMemory::getInstance().pushCasicIris(irisInfo); + + // Display is finished, push back image buffer to buffer queue + ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow); + + // 只在识别界面才显示画面 + if (ui->wgtIdentifying->currentIndex() == 0) { + // Display the image + QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT); + ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp)); + } + + return; +} + +void IdentifyForm::showRecogFailure() +{ + SpeakerUtil::getInstance().speak("识别失败,请重试"); +// LOG_INFO("识别失败,请重试"); + + ui->wgtIdentifying->setCurrentIndex(2); + + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCamCtrl->stopCapture(); + + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} + +void IdentifyForm::showRecognizeResult(QString personId) +{ + QVariantMap matched = personDao.findRecordById(personId); + + QString deptName = matched.value("deptname").toString(); + QString personName = matched.value("name").toString(); + SpeakerUtil::getInstance().speak(QString("识别成功,%1%2").arg(deptName).arg(personName)); + LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString()); + + ui->wgtIdentifying->setCurrentIndex(1); + + // 查询并显示人员信息 + ui->labelName->setText(""); + ui->labelName->setText(personName); + ui->labelGender->setText(""); + ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString()); + ui->labelDept->setText(""); + ui->labelDept->setText(deptName); + ui->labelTs->setText(""); + ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); + + // 查询并显示头像 + QPixmap photo; + QString photoPath = QString("images/%1").arg(matched.value("avatar").toString()); + bool succ = photo.load(photoPath); + if (succ == false) { + photo.load(":/images/photo.png"); + } + + // 缩放到合适的尺寸 + float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例 + float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例 + + if (rp <= rl) { + // 如果图片的比例小则缩放到显示框的高度 + photo = photo.scaledToHeight(ui->labelPhoto->height()); + } else { + // 如果图片的比例大则缩放到显示框的宽度 + photo = photo.scaledToWidth(ui->labelPhoto->width()); + } + // 显示 + ui->labelPhoto->setPixmap(photo); + + // 执行数据库操作 + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别; + record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE); + record.insert("debug_info", CasicIrisRecState::getInstance().toString()); + recordDao.save(record); + LOG_INFO("识别成功记录保存成功"); + + // 返回工作状态和界面 + QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){ + ProMemory::getInstance().irisCamCtrl->startCapture(); + ProMemory::getInstance().irisRecogPro->setWorking(true); + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; + ui->labelIdenTips->setText(""); + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); + ui->wgtIdentifying->setCurrentIndex(0); + }); +} diff --git a/IdentifyForm.h b/IdentifyForm.h index f68954b..8196c19 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -1,39 +1,39 @@ -#ifndef IDENTIFYFORM_H -#define IDENTIFYFORM_H - -#include -#include - -#include "dao/SysPersonDao.h" -#include "dao/RecognitionRecordsDao.h" -#include "dao/util/CacheManager.h" -#include "utils/UtilInclude.h" -#include "ProMemory.h" - -QT_BEGIN_NAMESPACE -namespace Ui { class IdentifyForm; } -QT_END_NAMESPACE - -class IdentifyForm : public QWidget -{ - Q_OBJECT - -public: - IdentifyForm(QWidget *parent = nullptr); - ~IdentifyForm(); - - void updateIdentifyTips(QString tips); - -public slots: - void drawIrisImageOnFrame(QImage image); - - void showRecogFailure(); - void showRecognizeResult(QString personId); - -private: - Ui::IdentifyForm *ui; - SysPersonDao personDao; - RecognitionRecordsDao recordDao; - -}; -#endif // IDENTIFYFORM_H +#ifndef IDENTIFYFORM_H +#define IDENTIFYFORM_H + +#include +#include + +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" +#include "utils/UtilInclude.h" +#include "ProMemory.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class IdentifyForm; } +QT_END_NAMESPACE + +class IdentifyForm : public QWidget +{ + Q_OBJECT + +public: + IdentifyForm(QWidget *parent = nullptr); + ~IdentifyForm(); + + void updateIdentifyTips(QString tips); + +public slots: + void drawIrisImageOnFrame(); + + void showRecogFailure(); + void showRecognizeResult(QString personId); + +private: + Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; + +}; +#endif // IDENTIFYFORM_H diff --git a/IdentifyForm.ui b/IdentifyForm.ui index 7a89ce4..def6ccf 100644 --- a/IdentifyForm.ui +++ b/IdentifyForm.ui @@ -1,199 +1,199 @@ - - - IdentifyForm - - - - 0 - 0 - 600 - 800 - - - - IdentifyForm - - - - - 0 - 0 - 600 - 800 - - - - 2 - - - - - - 105 - 35 - 393 - 512 - - - - - - - Qt::AlignCenter - - - - - - 0 - 650 - 600 - 80 - - - - background: transparent; - - - Qt::AlignCenter - - - - - - background: url(":/images/bg_success.png"); - - - - - 100 - 50 - 400 - 305 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - 200 - 400 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 498 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 595 - 300 - 60 - - - - background: transparent; - - - - - - - - - 200 - 691 - 300 - 60 - - - - background: transparent; - - - - - - - - - - - 100 - 50 - 400 - 300 - - - - background: transparent; - - - - - - :/images/iconWarn.png - - - Qt::AlignCenter - - - - - - 150 - 420 - 300 - 300 - - - - background: transparent; - - - - - - Qt::AlignCenter - - - - - - - - - - + + + IdentifyForm + + + + 0 + 0 + 600 + 800 + + + + IdentifyForm + + + + + 0 + 0 + 600 + 800 + + + + 2 + + + + + + 105 + 35 + 393 + 512 + + + + + + + Qt::AlignCenter + + + + + + 0 + 650 + 600 + 80 + + + + background: transparent; + + + Qt::AlignCenter + + + + + + background: url(":/images/bg_success.png"); + + + + + 100 + 50 + 400 + 305 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + 200 + 400 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 498 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 595 + 300 + 60 + + + + background: transparent; + + + + + + + + + 200 + 691 + 300 + 60 + + + + background: transparent; + + + + + + + + + + + 100 + 50 + 400 + 300 + + + + background: transparent; + + + + + + :/images/iconWarn.png + + + Qt::AlignCenter + + + + + + 150 + 420 + 300 + 300 + + + + background: transparent; + + + + + + Qt::AlignCenter + + + + + + + + + + diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp index 2d253e8..c33cbe8 100644 --- a/LockScreenForm.cpp +++ b/LockScreenForm.cpp @@ -1,31 +1,31 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "LockScreenForm.h" -#include "ui_LockScreenForm.h" - -LockScreenForm::LockScreenForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::LockScreenForm) -{ - ui->setupUi(this); -} - -LockScreenForm::~LockScreenForm() -{ - delete ui; -} - -void LockScreenForm::showLockScreenTime() -{ - QDateTime now = QDateTime::currentDateTime(); - ui->labelLockHour->setText(now.time().toString("HH")); - ui->labelLockMinute->setText(now.time().toString("mm")); - ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); - if (now.time().second() % 2 == 0) { - ui->labelLockSep->hide(); - } else { - ui->labelLockSep->show(); - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "LockScreenForm.h" +#include "ui_LockScreenForm.h" + +LockScreenForm::LockScreenForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::LockScreenForm) +{ + ui->setupUi(this); +} + +LockScreenForm::~LockScreenForm() +{ + delete ui; +} + +void LockScreenForm::showLockScreenTime() +{ + QDateTime now = QDateTime::currentDateTime(); + ui->labelLockHour->setText(now.time().toString("HH")); + ui->labelLockMinute->setText(now.time().toString("mm")); + ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd")); + if (now.time().second() % 2 == 0) { + ui->labelLockSep->hide(); + } else { + ui->labelLockSep->show(); + } +} diff --git a/LockScreenForm.h b/LockScreenForm.h index 93aac7d..f53f308 100644 --- a/LockScreenForm.h +++ b/LockScreenForm.h @@ -1,28 +1,28 @@ -#ifndef LOCKSCREENFORM_H -#define LOCKSCREENFORM_H - -#include -#include - -#include "utils/UtilInclude.h" - -namespace Ui { -class LockScreenForm; -} - -class LockScreenForm : public QWidget -{ - Q_OBJECT - -public: - explicit LockScreenForm(QWidget *parent = nullptr); - ~LockScreenForm(); - -public slots: - void showLockScreenTime(); - -private: - Ui::LockScreenForm *ui; -}; - -#endif // LOCKSCREENFORM_H +#ifndef LOCKSCREENFORM_H +#define LOCKSCREENFORM_H + +#include +#include + +#include "utils/UtilInclude.h" + +namespace Ui { +class LockScreenForm; +} + +class LockScreenForm : public QWidget +{ + Q_OBJECT + +public: + explicit LockScreenForm(QWidget *parent = nullptr); + ~LockScreenForm(); + +public slots: + void showLockScreenTime(); + +private: + Ui::LockScreenForm *ui; +}; + +#endif // LOCKSCREENFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index 64644b2..81e12d1 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -1,119 +1,113 @@ - - - LockScreenForm - - - - 0 - 0 - 600 - 800 - - - - Form - - - - - 0 - 270 - 600 - 100 - - - - - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - 285 - 130 - 30 - 128 - - - - - Microsoft YaHei UI Light - 96 - - - - : - - - Qt::AutoText - - - false - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - 320 - 120 - 280 - 150 - - - - - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - 275 - 700 - 50 - 50 - - - - - - - :/images/lock.png - - - true - - - Qt::AlignCenter - - - - - - - - + + + LockScreenForm + + + + 0 + 0 + 600 + 800 + + + + Form + + + + + 0 + 270 + 600 + 100 + + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + 285 + 130 + 30 + 128 + + + + + Microsoft YaHei UI Light + 96 + + + + : + + + Qt::AutoText + + + false + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + 320 + 120 + 280 + 150 + + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + 275 + 700 + 50 + 50 + + + + + + + :/images/lock.png + + + true + + + Qt::AlignCenter + + + + + + + + diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 543d71c..31888a9 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -1,176 +1,182 @@ -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) -#endif - -#include "MainWindowForm.h" -#include "ui_MainWindowForm.h" - -MainWindowForm::MainWindowForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWindowForm) -{ - ui->setupUi(this); - - // 设置窗口透明和大小、位置 - this->setWindowFlags(Qt::FramelessWindowHint); - this->move(1400, 15); - this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); - - // 通过调色板的颜色来设置窗口的统一背景色 - qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); - - // 加载css文件设置控件样式 - QFile file(QApplication::applicationDirPath() + "/qss/main.css"); - if (file.open(QFile::ReadOnly)) - { - QString qssStr = QLatin1String(file.readAll()); - this->setStyleSheet(qssStr); - file.close(); - } - - // 初始化虹膜库 - ProMemory::getInstance().initIrisFeatures(); - - // 初始化各个界面的form - initFormsPtr(); - - // 设置标题文字 - ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); - ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); - - ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); - ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); - ui->labelLogo->hide(); - - // 初始化更新界面的定时器 - // 每秒执行一次 - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - TimeCounterUtil::getInstance().clockCounter->start(1000); - - // 初始化虹膜相机控制 - ProMemory::getInstance().irisCam = new IrisCameraController(this); - ProMemory::getInstance().irisCam->initIrisCamera(); - ProMemory::getInstance().irisCam->openIrisCamera(); - connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); - - LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); - qDebug() << QString("应用程序启动成功[Application Startup Success]"); - - // 启动后显示视频画面 工作状态 未开始识别 - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 - ui->wdgtStatced->setCurrentWidget(identifyForm); - - // 开始虹膜相机拍图 - ProMemory::getInstance().irisCam->startCapture(); - - // 识别线程开始工作 - initIrisRecogThread(); // 虹膜识别线程 - ProMemory::getInstance().irisRecogPro->setWorking(true); -} - -MainWindowForm::~MainWindowForm() -{ - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisRecogPro->exitThread(); - ProMemory::getInstance().irisRecogPro->deleteLater(); - ProMemory::getInstance().irisRecogPro->wait(); - - delete ui; - delete ProMemory::getInstance().irisRecogPro; -} - -void MainWindowForm::lockScreenHandler() -{ - ui->wdgtStatced->setCurrentWidget(lockScreenForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 - - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); - - ui->labelMainTime->hide(); - ui->labelMainDate->hide(); - ui->labelLogo->show(); - ui->labelLogo->setPixmap(QPixmap("images/logo.png")); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); -} - -void MainWindowForm::startIdentifyHandler() -{ - ui->wdgtStatced->setCurrentWidget(identifyForm); - ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; - ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 - identifyForm->updateIdentifyTips("识 别 中"); - TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); - - ui->labelMainTime->show(); - ui->labelMainDate->show(); - ui->labelLogo->hide(); - - // 重新绑定每秒的定时信号和槽函数 - disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); -} - -void MainWindowForm::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Escape: - QTimer::singleShot(100, qApp, [=](){ - QApplication::quit(); - }); - - default: - QWidget::keyPressEvent(event); - } -} - -void MainWindowForm::initFormsPtr() -{ - // 初始化各个form - lockScreenForm = new LockScreenForm(this); - identifyForm = new IdentifyForm(this); - - // 将form添加到statcked widget中 - ui->wdgtStatced->addWidget(identifyForm); - ui->wdgtStatced->addWidget(lockScreenForm); - - // 绑定按钮函数 -} - -void MainWindowForm::initIrisRecogThread() -{ - // 虹膜识别处理过程 - ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); - - // 绑定信号与槽函数 - // 识别成功 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); - - // 识别失败 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); - - // 找到眼睛 开始识别 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); - - // 持续没找到目标 待机 - connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); - - ProMemory::getInstance().irisRecogPro->start(); -} - -void MainWindowForm::updateBannerTime() -{ - QDateTime now = QDateTime::currentDateTime(); - if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) - { - ui->labelMainTime->setText(now.toString("HH:mm:ss")); - - if (now.toString("HH:mm:ss") == "00:00:00") { - ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); - } - } -} +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "MainWindowForm.h" +#include "ui_MainWindowForm.h" + +MainWindowForm::MainWindowForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::MainWindowForm) +{ + ui->setupUi(this); + + // 设置窗口透明和大小、位置 + this->setWindowFlags(Qt::FramelessWindowHint); +// this->move(1400, 15); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + // 加载css文件设置控件样式 + QFile file(QApplication::applicationDirPath() + "/qss/main.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + // 初始化虹膜库 + ProMemory::getInstance().initIrisFeatures(); + + // 初始化各个界面的form + initFormsPtr(); + + // 设置标题文字 + ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS); + ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION); + + ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); + + // 初始化更新界面的定时器 + // 每秒执行一次 + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + TimeCounterUtil::getInstance().clockCounter->start(1000); + + // 初始化虹膜相机控制 + ProMemory::getInstance().irisCamCtrl = new IrisCameraController(); + ProMemory::getInstance().irisCamCtrl->openIrisCamera(); + + connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame); + TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + qDebug() << QString("应用程序启动成功[Application Startup Success]"); + + // 启动后显示视频画面 工作状态 未开始识别 + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面 + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态 + ui->wdgtStatced->setCurrentWidget(identifyForm); + + // 开始虹膜相机拍图 + ProMemory::getInstance().irisCamCtrl->startCapture(); + + // 识别线程开始工作 + initIrisRecogThread(); // 虹膜识别线程 + ProMemory::getInstance().irisRecogPro->setWorking(true); +} + +MainWindowForm::~MainWindowForm() +{ + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisRecogPro->exitThread(); + ProMemory::getInstance().irisRecogPro->deleteLater(); + ProMemory::getInstance().irisRecogPro->wait(); + + delete ui; + delete ProMemory::getInstance().irisRecogPro; +} + +void MainWindowForm::lockScreenHandler() +{ + ui->wdgtStatced->setCurrentWidget(lockScreenForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机 + + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL); + + ui->labelMainTime->hide(); + ui->labelMainDate->hide(); + ui->labelLogo->show(); + ui->labelLogo->setPixmap(QPixmap("images/logo.png")); + + LOG_INFO("长时间未找到眼睛,开始待机"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); +} + +void MainWindowForm::startIdentifyHandler() +{ + ui->wdgtStatced->setCurrentWidget(identifyForm); + ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; + ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中 + identifyForm->updateIdentifyTips("识 别 中"); + TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); + + ui->labelMainTime->show(); + ui->labelMainDate->show(); + ui->labelLogo->hide(); + + LOG_INFO("找到眼睛,结束待机,开始工作"); + + // 重新绑定每秒的定时信号和槽函数 + disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); + connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime); +} + +void MainWindowForm::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, [=](){ + QApplication::quit(); + }); + + default: + QWidget::keyPressEvent(event); + } +} + +void MainWindowForm::initFormsPtr() +{ + // 初始化各个form + lockScreenForm = new LockScreenForm(this); + identifyForm = new IdentifyForm(this); + + // 将form添加到statcked widget中 + ui->wdgtStatced->addWidget(identifyForm); + ui->wdgtStatced->addWidget(lockScreenForm); + + // 绑定按钮函数 +} + +void MainWindowForm::initIrisRecogThread() +{ + // 虹膜识别处理过程 + ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this); + + // 绑定信号与槽函数 + // 识别成功 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult); + + // 识别失败 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure); + + // 找到眼睛 开始识别 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler); + + // 持续没找到目标 待机 + connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler); + + ProMemory::getInstance().irisRecogPro->start(); +} + +void MainWindowForm::updateBannerTime() +{ + QDateTime now = QDateTime::currentDateTime(); + if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM) + { + ui->labelMainTime->setText(now.toString("HH:mm:ss")); + + if (now.toString("HH:mm:ss") == "00:00:00") { + ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd")); + } + } +} diff --git a/MainWindowForm.h b/MainWindowForm.h index 1e5d49a..9858b2a 100644 --- a/MainWindowForm.h +++ b/MainWindowForm.h @@ -1,43 +1,43 @@ -#ifndef MAINWINDOWFORM_H -#define MAINWINDOWFORM_H - -#include -#include -#include - -#include "utils/UtilInclude.h" -#include "ProMemory.h" -#include "LockScreenForm.h" -#include "IdentifyForm.h" - -namespace Ui { -class MainWindowForm; -} - -class MainWindowForm : public QWidget -{ - Q_OBJECT - -public: - explicit MainWindowForm(QWidget *parent = nullptr); - ~MainWindowForm(); - -public slots: - void lockScreenHandler(); - void startIdentifyHandler(); - -private: - Ui::MainWindowForm *ui; - LockScreenForm * lockScreenForm; - IdentifyForm * identifyForm; - - void keyPressEvent(QKeyEvent *event); - - void initFormsPtr(); - void initIrisRecogThread(); - -private slots: - void updateBannerTime(); -}; - -#endif // MAINWINDOWFORM_H +#ifndef MAINWINDOWFORM_H +#define MAINWINDOWFORM_H + +#include +#include +#include + +#include "utils/UtilInclude.h" +#include "ProMemory.h" +#include "LockScreenForm.h" +#include "IdentifyForm.h" + +namespace Ui { +class MainWindowForm; +} + +class MainWindowForm : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowForm(QWidget *parent = nullptr); + ~MainWindowForm(); + +public slots: + void lockScreenHandler(); + void startIdentifyHandler(); + +private: + Ui::MainWindowForm *ui; + LockScreenForm * lockScreenForm; + IdentifyForm * identifyForm; + + void keyPressEvent(QKeyEvent *event); + + void initFormsPtr(); + void initIrisRecogThread(); + +private slots: + void updateBannerTime(); +}; + +#endif // MAINWINDOWFORM_H diff --git a/MainWindowForm.ui b/MainWindowForm.ui index 221a090..79949db 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -1,123 +1,123 @@ - - - MainWindowForm - - - - 0 - 0 - 600 - 1024 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - background: url(":images/bg_title.png") - - - - - 0 - 0 - 600 - 84 - - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - 0 - 84 - 600 - 40 - - - - - - - Qt::AlignCenter - - - - - - 246 - 20 - 108 - 72 - - - - - - - images/logo.png - - - true - - - Qt::AlignCenter - - - - - - - - - - - - - - TextLabel - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - + + + MainWindowForm + + + + 0 + 0 + 600 + 1024 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + background: url(":images/bg_title.png") + + + + + 0 + 0 + 600 + 84 + + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + 0 + 84 + 600 + 40 + + + + + + + Qt::AlignCenter + + + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + + + + + + + + + + + + + TextLabel + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/ProMemory.cpp b/ProMemory.cpp index 18e4b3e..0eacecb 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -16,14 +16,12 @@ void ProMemory::pushCasicIris(CasicIrisInfo irisInfo) { - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 10) { QStack empty; std::swap(empty, irisQueue); } - irisQueue.push(irisInfo); mutex.unlock(); } @@ -31,13 +29,11 @@ { CasicIrisInfo result; - QMutex mutex; mutex.lock(); if (this->irisQueue.size() > 0) { result = irisQueue.pop(); } - mutex.unlock(); return result; @@ -47,11 +43,8 @@ { int size = 0; - QMutex mutex; mutex.lock(); - size = this->irisQueue.size(); - mutex.unlock(); return size; @@ -60,61 +53,23 @@ { bool empty = true; - QMutex mutex; mutex.lock(); - empty = this->irisQueue.isEmpty(); - mutex.unlock(); return empty; } void ProMemory::clearIrisQueue() { - QMutex mutex; mutex.lock(); - QStack empty; std::swap(empty, irisQueue); - mutex.unlock(); } void ProMemory::initIrisFeatures() { IrisDataDao irisDao; - /* - CasicIrisFeature leftFeature; - leftFeature.irisId = 1; - leftFeature.personId = "11left"; - leftFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\left-code.bmp", 0); - leftFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\left-mask.bmp", 0); - - CasicIrisInfo irisInfo; - irisInfo.irisCode = leftFeature.irisCode; - irisInfo.maskNorm = leftFeature.maskNorm; - leftFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); - - CasicIrisFeature rightFeature; - rightFeature.irisId = 2; - rightFeature.personId = "11right"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\right-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\right-mask.bmp", 0); - - CasicIrisInfo irisInfo2; - irisInfo2.irisCode = rightFeature.irisCode; - irisInfo2.maskNorm = rightFeature.maskNorm; - rightFeature.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo2); - - this->irisFeatures.append(leftFeature); - this->irisFeatures.append(rightFeature); - - QVariantMap obj; - obj.insert("person_id", "12097912071815954432"); - obj.insert("left_iris_code1", leftFeature.irisFeatureCode); - obj.insert("right_iris_code1", rightFeature.irisFeatureCode); - irisDao.save(obj); - */ QVector irisDataList = irisDao.findAllRecord(); for (QVariantMap iris : irisDataList) { diff --git a/ProMemory.h b/ProMemory.h index f57594a..cf1fe42 100644 --- a/ProMemory.h +++ b/ProMemory.h @@ -1,4 +1,4 @@ -#ifndef PROMEMORY_H +#ifndef PROMEMORY_H #define PROMEMORY_H #include @@ -13,7 +13,6 @@ #include "device/iris/IrisRecogProcess.h" class IrisCameraController; -class IrisRegistProcess; class IrisRecogProcess; class ProMemory @@ -37,12 +36,11 @@ volatile int widgeFrame = 0; // 当前显示的界面 volatile int appState = 0; // 当前程序所处的状态 - void initIrisFeatures(); -// void initIrisFeatures(QString personId = ""); // 初始化虹膜特征值集合 + void initIrisFeatures(); // 初始化虹膜特征值集合 QVector getIrisFeatures(); - IrisCameraController * irisCam; + IrisCameraController * irisCamCtrl; IrisRecogProcess * irisRecogPro; SocketClientUtil client; @@ -50,6 +48,8 @@ private: ProMemory(); + QMutex mutex; + QStack irisQueue; // 虹膜信息队列 QVector irisFeatures; // 虹膜特征值集合 }; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index e41ed26..e3c0735 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -1,8 +1,8 @@ -#ifndef CASICIRISINFO_H +#ifndef CASICIRISINFO_H #define CASICIRISINFO_H #include -#include "opencv2/opencv.hpp" +#include #include "CasicSegResult.h" struct CasicIrisInfo @@ -10,6 +10,9 @@ // 是否有眼睛, 默认为false bool hasEye = false; + // post process + bool postProcSucc = false; + // 眼部图像 // 后续计算需要使用 cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index c528381..d33c7ea 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -91,6 +91,11 @@ cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); + if (irisInfo.matData.empty() == true) { + irisInfo.hasEye = false; + return irisInfo; + } + // ★分类器对象调用 cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize); @@ -122,7 +127,6 @@ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x小于240则x=240 -// center.x = center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5; } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) { // x大于1040则x=1040 @@ -149,6 +153,7 @@ cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; + irisInfo.postProcSucc = false; irisInfo.matData = cutSize; return irisInfo; @@ -160,36 +165,11 @@ return irisInfo; } -CasicIrisInfo casic::iris::CasicIrisInterface::irisCodeExtract(CasicIrisInfo irisInfo) -{ - - QElapsedTimer timer; - timer.start(); - -// QSocketClientUtil * clientUtil = new QSocketClientUtil(); - - QByteArray data((char*)irisInfo.matData.data, 640*480); - - std::cout << "extract iris code" << std::endl; - -// clientUtil->sendData(data); -// if (response.size() == 1024) -// { -// QLog::getInstance()->logger()->debug(QString("特征值提取[耗时: %1ms][特征值: %2]\n") -// .arg(timer.elapsed()) -// .arg(QByteUtil::binToHexString(response))); -// } else -// { -// std::cout << response.toStdString() << std::endl; -// } - - return irisInfo; -} - - CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo) { - std::vector irisCircle, pupilCircle; // x,y,r +// std::vector irisCircle, pupilCircle; // x,y,r + std::vector irisCircle(0); // x,y,r + std::vector pupilCircle(0); // x,y,r iristrt::CasicSegPostProcess segPost; cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows)); @@ -199,6 +179,7 @@ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle); if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0) { + irisInfo.postProcSucc = false; return irisInfo; } // std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl; @@ -208,18 +189,21 @@ int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - int dis = iristrt::point_distance(iris_x,iris_y,pupil_x,pupil_y); + int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y); if(!(dis + pupil_r < iris_r)) { // pupil circle doesn't contained in iris circle + irisInfo.postProcSucc = false; return irisInfo; } cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]); - // std::cout << "finish normalize" << std::endl; +// std::cout << "finish normalize" << std::endl; +// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm); irisInfo.irisCode = rec.encodeToImage(imageNorm); + irisInfo.postProcSucc = true; return irisInfo; } diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index 26fbedc..7f91d68 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -1,4 +1,4 @@ -#ifndef CASICIRISINTERFACE_H +#ifndef CASICIRISINTERFACE_H #define CASICIRISINTERFACE_H #include "CasicIrisInfo.h" @@ -24,7 +24,6 @@ CasicIrisInfo findEye(CasicIrisInfo irisInfo); CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo); CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo); - CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); QByteArray extractFeature(CasicIrisInfo irisInfo); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index ad456b4..d9edb67 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -1,11 +1,11 @@ -#include "CasicIrisRec.h" +#include "CasicIrisRec.h" #include #include #include #include #include -#include +#include using Eigen::MatrixXd; using Eigen::MatrixXi; @@ -34,8 +34,8 @@ int height = NORM_HEIGHT; int realHeight = height + 2; int angledivisions = width - 1; - int rows = image.rows; - int cols = image.cols; +// int rows = image.rows; +// int cols = image.cols; double ox = pupil_x - iris_x; double oy = pupil_y - iris_y; @@ -386,6 +386,8 @@ uchar ** irisData2 = reduceIrisCode(feature2); uchar ** irisMask2 = reduceIrisMask(feature2); +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; + int shift = 10; float score = 1.0; @@ -400,6 +402,7 @@ int row = pos.first / mvApplicationPoints[0].first - 1; int col = (pos.second + s + width) % width; +// std::cout << "array: " << row << ", " << pos.second << std::endl; if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { uchar tmp1 = irisData1[row + height * n][col]; @@ -410,7 +413,7 @@ } } - //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; +// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl; mean = mean / count; score = mean < score ? mean : score; @@ -439,7 +442,7 @@ { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); - copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); + cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0); for (int i = 0; i < pSrc.rows; i++) { for (int j = 0; j < width; j++) { @@ -464,6 +467,8 @@ } } +// std::cout << "reduce iris code, length: " << width * height << std::endl; + return reduceCode; } @@ -482,6 +487,8 @@ } } +// std::cout << "reduce iris mask, length: " << width * height << std::endl; + return irisMask; } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index 2d9616e..3d5193b 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -1,9 +1,9 @@ -#ifndef CASIC_IRIS_REC +#ifndef CASIC_IRIS_REC #define CASIC_IRIS_REC #define NORM_WIDTH 512 #define NORM_HEIGHT 64 -#define M_PI 3.1415926535897323846 +//#define M_PI 3.1415926535897323846 #include #include diff --git a/casic/iris/CasicSegPostProcess.cpp b/casic/iris/CasicSegPostProcess.cpp index 740beb7..e81b0a6 100644 --- a/casic/iris/CasicSegPostProcess.cpp +++ b/casic/iris/CasicSegPostProcess.cpp @@ -1,13 +1,16 @@ -#include "CasicSegPostProcess.h" +#include "CasicSegPostProcess.h" #include +#include +#include +#include "utils/LogUtil.h" namespace iristrt { std::vector CasicSegPostProcess::getConnections(cv::Mat input, int connectivity) { cv::Mat output; - int nLabels = connectedComponents(input, output, connectivity); + int nLabels = cv::connectedComponents(input, output, connectivity); output.convertTo(output, CV_8UC1, 1); std::vector conns; @@ -81,7 +84,7 @@ int CasicSegPostProcess::getChessboardDistance(cv::Mat con1, cv::Mat con2, int chessboardDistance) { // mask contours std::vector> c1; - findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con1, c1,cv:: RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c1.size() " << c1.size() << endl; std::vector c1All; for (auto c : c1) { @@ -92,7 +95,7 @@ // other contours std::vector> c2; - findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); + cv::findContours(con2, c2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); //cout << "c2.size() " << c2.size() << endl; std::vector c2All; for (auto c : c2) { @@ -195,19 +198,26 @@ iris.convertTo(iris, CV_8UC1); pupil.convertTo(pupil, CV_8UC1); - threshold(mask, mask, 127, 255, cv::THRESH_BINARY); - threshold(iris, iris, 90, 255, cv::THRESH_BINARY); - threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); + cv::threshold(mask, mask, 127, 255, cv::THRESH_BINARY); + cv::threshold(iris, iris, 90, 255, cv::THRESH_BINARY); + cv::threshold(pupil, pupil, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); - morphologyEx(iris, iris, cv::MORPH_CLOSE, element); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::morphologyEx(iris, iris, cv::MORPH_CLOSE, element); +/* + std::string pupilSeg = QString("%1/%2/%3-pupil-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-thre.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilSeg, pupil); + cv::imwrite(maskSeg, mask); + cv::imwrite(irisSeg, iris); +*/ +// cv::imshow("mask",mask); +// cv::imshow("iris",iris); +// cv::imshow("pupil",pupil); +// cv::waitKey(0); -// cv::imshow("mask",mask); -// cv::imshow("iris",iris); -// cv::imshow("pupil",pupil); -// cv::waitKey(0); - -// std::cout << "get connection ..." << std::endl; +// std::cout << "get connection ..." << std::endl; std::vector maskCons = getConnections(mask, 8); std::vector irisCons = getConnections(iris, 8); @@ -218,7 +228,7 @@ return false; } -// std::cout << "get triple set ..." << std::endl; +// std::cout << "get triple set ..." << std::endl; std::vector tripleSet = getTripleSet(maskCons, irisCons, pupilCons, chessboard_distance); @@ -226,59 +236,58 @@ return false; } -// std::cout << "get max triple ..." << std::endl; +// std::cout << "get max triple ..." << std::endl; CasicTriplet maxTriple = getMaxTriple(tripleSet); //showTriple(maxTriple); -// std::cout << "least Square Circle Fitting ..." << std::endl; +// std::cout << "least Square Circle Fitting ..." << std::endl; cv::Mat bestIris = maxTriple.irisConn; std::vector outPoints; - findNonZero(bestIris, outPoints); + cv::findNonZero(bestIris, outPoints); irisCircle = leastSquareCircleFitting(outPoints); int iris_x = irisCircle[0]; int iris_y = irisCircle[1]; int iris_r = irisCircle[2]; +// LOG_INFO(QString("outPoints size: %1").arg(outPoints.size()).toStdString()); + cv::Mat bestPupil = maxTriple.pupilConn; std::vector> innerCounter; - findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bestPupil, innerCounter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector innerPoints; - for (auto c : innerCounter) { + +// LOG_INFO(QString("innerPoints size: %1, %2").arg(innerPoints.size()).arg(innerCounter.size()).toStdString()); + + for (auto c : innerCounter) { innerPoints.insert(innerPoints.end(), c.begin(), c.end()); +// LOG_INFO(QString("innerPoints: %1, %2, %3, %4").arg(c.begin()->x).arg(c.begin()->y).arg(c.end()->x).arg(c.end()->y).toStdString()); } pupilCircle = leastSquareCircleFitting(innerPoints); int pupil_x = pupilCircle[0]; int pupil_y = pupilCircle[1]; int pupil_r = pupilCircle[2]; - //cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << endl; - //cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << endl; +// LOG_INFO(QString("innerPoints size: %1").arg(innerPoints.size()).toStdString()); +/* + std::string pupilbest = QString("%1/%2/%3-pupil-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisbest = QString("%1/%2/%3-iris-best.bmp").arg("/home/casic/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(pupilbest, bestPupil); + cv::imwrite(irisbest, bestIris); +*/ +// std::cout << "iris: " << iris_x << " " << iris_y << " " << iris_r << std::endl; +// std::cout << "pupil:" << pupil_x << " " << pupil_y << " " << pupil_r << std::endl; +// LOG_INFO(QString("iris: %1, %2, %3").arg(iris_x).arg(iris_y).arg(iris_r).toStdString()); +// LOG_INFO(QString("pupil: %1, %2, %3").arg(pupil_x).arg(pupil_y).arg(pupil_r).toStdString()); -// std::cout << "bitwise_and ..." << std::endl; +// std::cout << "bitwise_and ..." << std::endl; cv::Mat circleMask = cv::Mat::zeros(mask.size(), CV_8UC1); - circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); - circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); + cv::circle(circleMask,cv::Point(iris_x, iris_y), iris_r, 255, -1); + cv::circle(circleMask,cv::Point(pupil_x, pupil_y), pupil_r, 0, -1); cv::bitwise_and(mask, circleMask, mask); - // show result -// cv::imshow("circleMask", circleMask); -// cv::waitKey(0); - -// cv::Mat three_mask = cv::Mat::zeros(mask.rows, mask.cols, CV_8UC3); -// std::vector channels_m; -// for (int i = 0; i < 3; i++) -// { -// channels_m.push_back(mask); -// } -// merge(channels_m, three_mask); - -// circle(three_mask, cv::Point(iris_x, iris_y), iris_r, cv::Scalar(0, 0, 255), 1); -// circle(three_mask, cv::Point(pupil_x, pupil_y), pupil_r, cv::Scalar(0, 0, 255), 1); -// cv::imshow("three_mask", three_mask); -// cv::waitKey(0); return true; } diff --git a/casic/iris/CasicSegResult.h b/casic/iris/CasicSegResult.h index 7e682eb..a3b6c86 100644 --- a/casic/iris/CasicSegResult.h +++ b/casic/iris/CasicSegResult.h @@ -1,7 +1,7 @@ -#ifndef CASIC_SEG_RESULT +#ifndef CASIC_SEG_RESULT #define CASIC_SEG_RESULT -#include "opencv2/opencv.hpp" +#include namespace iristrt { diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 63eda4d..8ceb89d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -41,7 +41,7 @@ result.append(item); } - LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_TRACE(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } diff --git a/device/AcquisitionThread.cpp b/device/AcquisitionThread.cpp new file mode 100644 index 0000000..500f5b1 --- /dev/null +++ b/device/AcquisitionThread.cpp @@ -0,0 +1,528 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.cpp +\brief CAcquisitionThread Class implementation file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#include "AcquisitionThread.h" + +//---------------------------------------------------------------------------------- +/** +\Constructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::CAcquisitionThread(QObject *parent) : + QThread(parent), + m_ui64AcquisitionBufferNum(0), + m_nFrameCount(0), + m_bAcquisitionThreadFlag(false), + m_hDevice(NULL), + m_bSoftTriggerOn(false), + m_i64ColorFilter(0), + m_i64ImageMaxWidth(0), + m_i64ImageWidth(0), + m_i64ImageMaxHeight(0), + m_i64ImageHeight(0), + m_bColorFilter(false), + m_bColorCorrection(false), + m_bGammaRegulation(false), + m_bContrastRegulation(false), + m_i64ColorCorrection(0), + m_pGammaLut(NULL), + m_pContrastLut(NULL), + m_pstarrFrameBuffer(NULL), + m_pRaw8Image(NULL), + m_pImageElement0(NULL), + m_pImageElement1(NULL), + m_pImageElement2(NULL), + m_objParamMutex(QMutex::Recursive), + m_objDequeMutex(QMutex::Recursive) +{ + +} +//---------------------------------------------------------------------------------- +/** +\Destructor +*/ +//---------------------------------------------------------------------------------- +CAcquisitionThread::~CAcquisitionThread() +{ + // Release all resources + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + RELEASE_ALLOC_ARR(m_pRaw8Image); + + RELEASE_ALLOC_ARR(m_pGammaLut); + RELEASE_ALLOC_ARR(m_pContrastLut); + + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); +} + +//---------------------------------------------------------------------------------- +/** +\Main function of Acquisition-thread, Acquisition-thread run start from here +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::run() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + PROC_STATUS emProcStatus = PROC_SUCCESS; + uint32_t ui32FrameNum = 0; + + // Acquisition frame count reset + m_nFrameCount = 0; + + // Acquisition thread loop + while (m_bAcquisitionThreadFlag) + { + // Acquire ui32FrameElementNum frame data from buffer queue + emStatus = GXDQAllBufs(m_hDevice, m_pstarrFrameBuffer, m_ui64AcquisitionBufferNum, &ui32FrameNum, 1000); + + // Continue when GXDQAllBufs timeout, other error will quit acquisiton loop + if (emStatus != GX_STATUS_SUCCESS) + { + if (emStatus == GX_STATUS_TIMEOUT) + { + continue; + } + else + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + } + + // Return all bufs back when met the last frame is incomplete + if (m_pstarrFrameBuffer[ui32FrameNum - 1]->nStatus != GX_FRAME_STATUS_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + continue; + } + + // Get a buffer for process new image + QImage *pobjImageBuffer = PopFrontFromEmptyBufferDeque(); + // If buffer deque is empty, get one buffer from image show deque + if (pobjImageBuffer == NULL) + { + pobjImageBuffer = PopFrontFromShowImageDeque(); + } + + // Assign the address of the first pixel of the QImage to a temporary variable for image processing + unsigned char* pImageProcess = pobjImageBuffer->bits(); + + // Image processing, Raw to RGB24 and image improvment, if process failed put buffer back to buffer deque + emProcStatus = ImageProcess(m_pstarrFrameBuffer[ui32FrameNum - 1], pImageProcess); + if (emProcStatus != PROC_SUCCESS) + { + emStatus = GXQAllBufs(m_hDevice); + PushBackToEmptyBufferDeque(pobjImageBuffer); + break; + } + + // Image processing is done push processed buffer to show image deque + PushBackToShowImageDeque(pobjImageBuffer); + + // Put all buffers back to deque + emStatus = GXQAllBufs(m_hDevice); + if (emStatus != GX_STATUS_SUCCESS) + { + //Get Acquisition error and send it to main thread + GetAcquistionErrorString(emStatus); + break; + } + + // Get acquisition frame rate + for (uint32_t i = 0; i < ui32FrameNum; i++) + { + m_nFrameCount++; + } + } + + // Clear both deque when acquisition is stop + ClearDeque(); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to empty buffer deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToEmptyBufferDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objEmptyBufferDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Push back to show image deque +\param[in] pobjImage Buffer pointer to push back +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::PushBackToShowImageDeque(QImage* pobjImage) +{ + QMutexLocker locker(&m_objDequeMutex); + m_objShowImageDeque.push_back(pobjImage); + + return; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from empty buffer deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromEmptyBufferDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objEmptyBufferDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objEmptyBufferDeque.front(); + m_objEmptyBufferDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Pop front from show image deque +\param[in] +\param[out] +\return QImage* pobjImage If deque not empty return a buffer pointer + NULL If deque is empty return NULL +*/ +//---------------------------------------------------------------------------------- +QImage* CAcquisitionThread::PopFrontFromShowImageDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + if (m_objShowImageDeque.empty()) + { + return NULL; + } + + QImage* pobjImage = m_objShowImageDeque.front(); + m_objShowImageDeque.pop_front(); + + return pobjImage; +} + +//---------------------------------------------------------------------------------- +/** +\Clear both deque +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::ClearDeque() +{ + QMutexLocker locker(&m_objDequeMutex); + + m_objEmptyBufferDeque.clear(); + m_objShowImageDeque.clear(); + + return; +} + + +//---------------------------------------------------------------------------------- +/** +\Process Raw image to RGB image and do image improvment +\param[in] pstFrameBuffer Raw image acquired +\param[out] pImageProcess Processed image +\return PROC_STATUS PROC_SUCCESS process successed + PROC_FAIL process failed +*/ +//---------------------------------------------------------------------------------- +PROC_STATUS CAcquisitionThread::ImageProcess(const PGX_FRAME_BUFFER pstFrameBuffer, unsigned char* pImageProcess) +{ + VxInt32 emDxStatus = DX_OK; + + // Convert RAW8 or RAW16 image to RGB24 image + switch (pstFrameBuffer->nPixelFormat) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_MONO8_SIGNED: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + // Convert to the RGB + emDxStatus = DxRaw8toRGB24((unsigned char*)pstFrameBuffer->pImgBuf, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_2_9); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + // Convert to the Raw8 image + emDxStatus = DxRaw16toRaw8((unsigned char*)pstFrameBuffer->pImgBuf, m_pRaw8Image, m_i64ImageWidth, m_i64ImageHeight, DX_BIT_4_11); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + // Convert to the RGB24 image + emDxStatus = DxRaw8toRGB24((unsigned char*)m_pRaw8Image, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, + RAW2RGB_NEIGHBOUR, DX_PIXEL_COLOR_FILTER(m_i64ColorFilter), false); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + break; + } + default: + { + // Enter this branch when pixel format not support + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + // Image improvment params will changed in other thread, must being locked + QMutexLocker locker(&m_objParamMutex); + + int64_t i64ColorCorrection = m_bColorCorrection ? m_i64ColorCorrection : 0; + unsigned char* pGammaLut = m_bGammaRegulation ? m_pGammaLut : NULL; + unsigned char* pContrastLut = m_bContrastRegulation ? m_pContrastLut : NULL; + + if (i64ColorCorrection != 0 || pGammaLut != NULL || pContrastLut != NULL) + { + emDxStatus = DxImageImprovment(pImageProcess, pImageProcess, m_i64ImageWidth, m_i64ImageHeight, i64ColorCorrection, pContrastLut, pGammaLut); + if (emDxStatus != DX_OK) + { + emit SigImageProcError(emDxStatus); + return PROC_FAIL; + } + } + + return PROC_SUCCESS; +} + + +//---------------------------------------------------------------------------------- +/** +\Get device handle from main-thread +\param[in] +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetDeviceHandle(GX_DEV_HANDLE hDeviceHandle) +{ + m_hDevice = hDeviceHandle; +} + +//---------------------------------------------------------------------------------- +/** +\Alloc QImage resource for show frames on ImageLabel +\param[in] +\param[out] +\return bool true : Prepare success +\ false: Prepare fail +*/ +//---------------------------------------------------------------------------------- +bool CAcquisitionThread::PrepareForShowImg() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + int64_t i64ImageWidth = 0; + int64_t i64ImageHeight = 0; + + // Release PGX_FRAME_BUFFER array + RELEASE_ALLOC_ARR(m_pstarrFrameBuffer); + + // PGX_FRAME_DATA is pointer of GX_FRAME_DATA, pointer array for image acquisition + try + { + m_pstarrFrameBuffer = new PGX_FRAME_BUFFER[m_ui64AcquisitionBufferNum]; + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate PGX_FRAME_BUFFER array failed! "); + return false; + } + + // Get the type of Bayer conversion. whether is a color camera. + emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Color image + if(m_bColorFilter) + { + emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_i64ColorFilter); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + } + + // Get the image width + emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &i64ImageWidth); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Get the image height + emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &i64ImageHeight); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // If width or height is changed, realloc image buffer + if (i64ImageWidth != m_i64ImageWidth || i64ImageHeight != m_i64ImageHeight) + { + m_i64ImageWidth = i64ImageWidth; + m_i64ImageHeight = i64ImageHeight; + + RELEASE_ALLOC_ARR(m_pRaw8Image); + RELEASE_ALLOC_MEM(m_pImageElement0); + RELEASE_ALLOC_MEM(m_pImageElement1); + RELEASE_ALLOC_MEM(m_pImageElement2); + + try + { + // Allocate raw8 frame buffer for DxRaw16toRaw8 + m_pRaw8Image = new unsigned char[m_i64ImageWidth * m_i64ImageHeight]; + + // Allocate three QImage buffer for deque acquisition + m_pImageElement0 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement1 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + m_pImageElement2 = new QImage(m_i64ImageWidth, m_i64ImageHeight, QImage::Format_RGB888); + } + catch (std::bad_alloc& e) + { + QMessageBox::about(NULL, "Error", "Start Acquisition Failed : Allocate image resources failed! "); + return false; + } + } + + // Clear deque if it is not empty + if (!m_objEmptyBufferDeque.empty()) + { + ClearDeque(); + } + + // Add buffer pointer to empty buffer deque + PushBackToEmptyBufferDeque(m_pImageElement0); + PushBackToEmptyBufferDeque(m_pImageElement1); + PushBackToEmptyBufferDeque(m_pImageElement2); + + return true; +} + + +//---------------------------------------------------------------------------------- +/** +\Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) +\param[in] emStatus Error code +\param[out] +\return void +*/ +//---------------------------------------------------------------------------------- +void CAcquisitionThread::GetAcquistionErrorString(GX_STATUS emError) +{ + char* error_info = NULL; + size_t size = 0; + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Get the length of the error message and alloc memory for error info + emStatus = GXGetLastError(&emError, NULL, &size); + + // Alloc memory for error info + try + { + error_info = new char[size]; + } + catch (std::bad_alloc& e) + { + emit SigAcquisitionError(QString("Alloc error info Faild!")); + return; + } + + // Get the error message and display + emStatus = GXGetLastError (&emError, error_info, &size); + + if (emStatus != GX_STATUS_SUCCESS) + { + emit SigAcquisitionError(QString("Interface of GXGetLastError call failed!")); + } + else + { + emit SigAcquisitionError(QString("%1").arg(QString(QLatin1String(error_info)))); + } + + // Release memory alloced + if (NULL != error_info) + { + delete[] error_info; + error_info = NULL; + } + + return; +} diff --git a/device/AcquisitionThread.h b/device/AcquisitionThread.h new file mode 100644 index 0000000..25a0919 --- /dev/null +++ b/device/AcquisitionThread.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------- +/** +\file AcquisitionThread.h +\brief CAcquisitionThread Class declaration file + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- +#ifndef ACQUISITIONTHREAD_H +#define ACQUISITIONTHREAD_H + +#include +#include +#include + +#include "Common.h" + +/// Image process status +enum PROC_STATUS +{ + PROC_SUCCESS = 0, + PROC_FAIL = -1 +}; + +class CAcquisitionThread : public QThread +{ + Q_OBJECT +public: + explicit CAcquisitionThread(QObject *parent = 0); + ~CAcquisitionThread(); + + /// Get device handle from main-thread + void GetDeviceHandle(GX_DEV_HANDLE); + + /// Alloc QImage resource for show frames on ImageLabel + bool PrepareForShowImg(); + + /// Push back to empty buffer deque + void PushBackToEmptyBufferDeque(QImage*); + + /// Push back to show image deque + void PushBackToShowImageDeque(QImage*); + + /// Pop front from show image deque + QImage* PopFrontFromShowImageDeque(); + + /// Pop front from empty buffer deque + QImage* PopFrontFromEmptyBufferDeque(); + + /// Clear both deque + void ClearDeque(); + + uint64_t m_ui64AcquisitionBufferNum; ///< Acquisition buffer number + uint32_t m_nFrameCount; ///< Acquisition frame count + bool m_bAcquisitionThreadFlag; ///< Acquistion thread run flag + GX_DEV_HANDLE m_hDevice; ///< Device Handle + +private: + /// Process Raw image to RGB image and do image improvment + PROC_STATUS ImageProcess(PGX_FRAME_BUFFER, unsigned char*); + + /// Get Acquisition error and send it to main thread(GXGetLastError can only get string from the thread which error occured) + void GetAcquistionErrorString(GX_STATUS); + + bool m_bSoftTriggerOn; ///< Trigger Mode is on + int64_t m_i64ColorFilter; ///< The bayer format + int64_t m_i64ImageMaxWidth; ///< The Maximum of image width + int64_t m_i64ImageWidth; ///< The image width + int64_t m_i64ImageMaxHeight; ///< The Maximum of image height + int64_t m_i64ImageHeight; ///< The image height + bool m_bColorFilter; ///< Support color pixel format or not + + bool m_bColorCorrection; ///< Flag : ColorCorrection is on or not + bool m_bGammaRegulation; ///< Flag : GammaRegulation is on or not + bool m_bContrastRegulation; ///< Flag : ContrastRegulation is on or not + int64_t m_i64ColorCorrection; ///< Color correction param + unsigned char* m_pGammaLut; ///< Gamma look up table + int m_nGammaLutLength; ///< Gamma look up table length + unsigned char* m_pContrastLut; ///< Contrast look up table + int m_nContrastLutLength; ///< Contrast look up table length + + PGX_FRAME_BUFFER* m_pstarrFrameBuffer; ///< Array of PGX_FRAME_BUFFER + unsigned char* m_pRaw8Image; ///< Intermediate variables between DxRaw16toRaw8 and DxRaw8toRGB24 + QImage* m_pImageElement0; ///< QImage for image showing + QImage* m_pImageElement1; ///< QImage for image showing + QImage* m_pImageElement2; ///< QImage for image showing + + std::deque m_objEmptyBufferDeque; ///< Empty buffer deque + std::deque m_objShowImageDeque; ///< Show image deque + + QMutex m_objParamMutex; ///< Mutex for cross thread parameters + QMutex m_objDequeMutex; ///< Mutex for deque + + +protected: + /// The starting point for acquisition thread. + /// Only code within this function are run in acquisition threads + void run(); + +signals: + /// Acquisition error occured signal + void SigAcquisitionError(QString); + + /// Image process error occured signal + void SigImageProcError(VxInt32); +}; + +#endif // ACQUISITIONTHREAD_H diff --git a/device/Common.h b/device/Common.h new file mode 100644 index 0000000..3d7bf52 --- /dev/null +++ b/device/Common.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------- +/** +\file Common.h +\brief Common function declare and define macros of GxViewer + +\version v1.0.1807.9271 +\date 2018-07-27 + +

Copyright (c) 2017-2018

+*/ +//---------------------------------------------------------------------------------- + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GxIAPI.h" +#include "DxImageProc.h" + +#define FRAMERATE_INCREMENT 0.1 +#define EXPOSURE_INCREMENT 1 +#define GAIN_INCREMENT 0.1 +#define WHITEBALANCE_DECIMALS 4 +#define WHITEBALANCE_INCREMENT 0.0001 + +/// Release memory allocated +#define RELEASE_ALLOC_MEM(obj) \ + if (obj != NULL) \ + { \ + delete obj; \ + obj = NULL; \ + } + +/// Release memory(array) allocated +#define RELEASE_ALLOC_ARR(obj) \ + if (obj != NULL) \ + { \ + delete[] obj; \ + obj = NULL; \ + } + + +#endif // COMMON_H diff --git a/device/IrisCameraCapEventHandler.h b/device/IrisCameraCapEventHandler.h index 8b976c5..94f5594 100644 --- a/device/IrisCameraCapEventHandler.h +++ b/device/IrisCameraCapEventHandler.h @@ -1,10 +1,9 @@ -#ifndef IRISCAMERACAPEVENTHANDLER_H +#ifndef IRISCAMERACAPEVENTHANDLER_H #define IRISCAMERACAPEVENTHANDLER_H #include #include -#include "include/opencv2/opencv.hpp" -#include "include/daheng/GalaxyIncludes.h" +#include #include "casic/iris/CasicIrisInterface.h" #include "ProMemory.h" diff --git a/device/IrisCameraController.cpp b/device/IrisCameraController.cpp index 0928176..4eea013 100644 --- a/device/IrisCameraController.cpp +++ b/device/IrisCameraController.cpp @@ -1,8 +1,8 @@ -#include "IrisCameraController.h" +#include "IrisCameraController.h" IrisCameraController::IrisCameraController(QObject *parent) : QObject(parent) { - this->irisCamHandler = new IrisCameraCapEventHandler(this); + initIrisCameraController(); } IrisCameraController::~IrisCameraController() { @@ -10,101 +10,204 @@ } -void IrisCameraController::initIrisCamera() +void IrisCameraController::initIrisCameraController() { - IGXFactory::GetInstance().Init(); + // Init GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXInitLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraInitError(); + LOG_ERROR("[CameraController]初始化虹膜相机失败"); + return ; + } + LOG_INFO("[CameraController]初始化虹膜相机成功"); //枚举设备 - IGXFactory::GetInstance().UpdateDeviceList(1000, irisCamList); - - this->OpenDevice(); + UpdateDeviceList(); } void IrisCameraController::openIrisCamera() { - //设置Buffer处理模式 - irisStreamFeaturePtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst"); + GX_STATUS emStatus = GX_STATUS_SUCCESS; - //注册回调函数 - irisStreamPtr->RegisterCaptureCallback(irisCamHandler, &irisCamPtr); + if (m_ui32DeviceNum > 0) { + emStatus = GXOpenDeviceByIndex(1, &m_hDevice); - //开启流层通道 - irisStreamPtr->StartGrab(); + if (emStatus == GX_STATUS_SUCCESS) { + LOG_INFO("[CameraController]开启虹膜相机成功"); - //发送开采命令 - irisFeaturePtr->GetCommandFeature("AcquisitionStart")->Execute(); + // isOpen flag set true + m_bOpen = true; - // 启动定时器 - TimeCounterUtil::getInstance().irisCapCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL); // 50ms执行一次定时器 + SetUpAcquisitionThread(); + } + } + + return; } void IrisCameraController::closeIrisCamera() { - + // Release GxiApi libary + GX_STATUS emStatus = GX_STATUS_SUCCESS; + emStatus = GXCloseLib(); + if (emStatus != GX_STATUS_SUCCESS) + { + emit irisCameraTermError(); + } } void IrisCameraController::startCapture() { // 获取定时器, 绑定定时函数 - connect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][startCapture]虹膜相机拍图").toStdString()); + bool bSetDone = false; + // Set acquisition buffer number + bSetDone = SetAcquisitionBufferNum(); + if (!bSetDone) + { + return; + } + + bool bPrepareDone = false; + // Alloc resource for image acquisition + bPrepareDone = m_pobjAcqThread->PrepareForShowImg(); + if (!bPrepareDone) + { + return; + } + + // Device start acquisition and start acquisition thread + StartAcquisition(); + + LOG_DEBUG(QString("[CameraController][startCapture]虹膜相机拍图").toStdString()); + + // Do not start timer when acquisition start failed + if (!m_bAcquisitionStart) + { + return; + } } void IrisCameraController::stopCapture() { - // 获取定时器, 绑定定时函数 - disconnect(TimeCounterUtil::getInstance().irisCapCounter, &QTimer::timeout, this, &IrisCameraController::getOneFaceFrm); -// LOG(DEBUG) << QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString(); // LOG_DEBUG(QString("[IrisCameraController][stopCapture]虹膜相机停止拍图").toStdString()); - + this->StopAcquisition(); } -void IrisCameraController::getOneFaceFrm() +void IrisCameraController::SetUpAcquisitionThread() { - // 发送软触发命令(在触发模式开启时有效) - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::getLeftAndRightEyeFrame() -{ - irisFeaturePtr->GetCommandFeature("TriggerSoftware")->Execute(); -} - -void IrisCameraController::OpenDevice() -{ - auto device = irisCamList.at(0); - - irisCamPtr = IGXFactory::GetInstance().OpenDeviceByUserID(device.GetUserID(), GX_ACCESS_EXCLUSIVE); - irisFeaturePtr = irisCamPtr->GetRemoteFeatureControl(); - - // 判断设备流是否大于零, 如果大于零则打开流 - int nStreamCount = irisCamPtr->GetStreamCount(); - if (nStreamCount > 0) + // if Acquisition thread is on Stop acquisition thread + if (m_pobjAcqThread != NULL) { - irisStreamPtr = irisCamPtr->OpenStream(0); - irisStreamFeaturePtr = irisStreamPtr->GetFeatureControl(); + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Release acquisition thread object + RELEASE_ALLOC_MEM(m_pobjAcqThread); } - // 建议用户在打开网络相机之后, 根据当前网络环境设置相机的流通道包长值, - // 以提高网络相机的采集性能, 设置方法参考以下代码。 - GX_DEVICE_CLASS_LIST objDeviceClass = irisCamPtr->GetDeviceInfo().GetDeviceClass(); - if(GX_DEVICE_CLASS_GEV == objDeviceClass) + // Instantiation acquisition thread + try { - // 判断设备是否支持流通道数据包功能 - if(true == irisFeaturePtr->IsImplemented("GevSCPSPacketSize")) - { - // 获取当前网络环境的最优包长值 - int nPacketSize = irisStreamPtr->GetOptimalPacketSize(); - // 将最优包长值设置为当前设备的流通道包长值 - irisFeaturePtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize); - } + m_pobjAcqThread = new CAcquisitionThread(); + m_pobjAcqThread->m_hDevice = m_hDevice; + } + catch (std::bad_alloc &e) + { + QMessageBox::about(NULL, "Allocate memory error", "Cannot allocate memory, please exit this app!"); + RELEASE_ALLOC_MEM(m_pobjAcqThread); + return; } - //设置采集模式为连续采集模式 - irisFeaturePtr->GetEnumFeature("AcquisitionMode")->SetValue("Continuous"); + return; +} - //设置触发模式关 - irisFeaturePtr->GetEnumFeature("TriggerMode")->SetValue("On"); - irisFeaturePtr->GetEnumFeature("TriggerSource")->SetValue("Software"); +void IrisCameraController::UpdateDeviceList() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + // Enumerate Devcie List + emStatus = GXUpdateDeviceList(&m_ui32DeviceNum, ENUMRATE_TIME_OUT); + + LOG_INFO(QString("[CameraController]枚举虹膜相机成功[%1]").arg(m_ui32DeviceNum).toStdString()); + + return; +} + +void IrisCameraController::StartAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + emStatus = GXStreamOn(m_hDevice); + + // Set acquisition thread run flag + m_pobjAcqThread->m_bAcquisitionThreadFlag = true; + + // Acquisition thread start + m_pobjAcqThread->start(); + + // isStart flag set true + m_bAcquisitionStart = true; + + return; +} + +void IrisCameraController::StopAcquisition() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + + m_pobjAcqThread->m_bAcquisitionThreadFlag = false; + m_pobjAcqThread->quit(); + m_pobjAcqThread->wait(); + + // Turn off stream + emStatus = GXStreamOff(m_hDevice); + + // isStart flag set false + m_bAcquisitionStart = false; + + return; +} + +bool IrisCameraController::SetAcquisitionBufferNum() +{ + GX_STATUS emStatus = GX_STATUS_SUCCESS; + uint64_t ui64BufferNum = 0; + int64_t i64PayloadSize = 0; + + // Get device current payload size + emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &i64PayloadSize); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Set buffer quantity of acquisition queue + if (i64PayloadSize == 0) + { + return false; + } + + // Calculate a reasonable number of Buffers for different payload size + // Small ROI and high frame rate will requires more acquisition Buffer + const size_t MAX_MEMORY_SIZE = 8 * 1024 * 1024; // The maximum number of memory bytes available for allocating frame Buffer + const size_t MIN_BUFFER_NUM = 5; // Minimum frame Buffer number + const size_t MAX_BUFFER_NUM = 450; // Maximum frame Buffer number + ui64BufferNum = MAX_MEMORY_SIZE / i64PayloadSize; + ui64BufferNum = (ui64BufferNum <= MIN_BUFFER_NUM) ? MIN_BUFFER_NUM : ui64BufferNum; + ui64BufferNum = (ui64BufferNum >= MAX_BUFFER_NUM) ? MAX_BUFFER_NUM : ui64BufferNum; + + emStatus = GXSetAcqusitionBufferNumber(m_hDevice, ui64BufferNum); + if (emStatus != GX_STATUS_SUCCESS) + { + return false; + } + + // Transfer buffer number to acquisition thread class for using GXDQAllBufs + m_pobjAcqThread->m_ui64AcquisitionBufferNum = ui64BufferNum; + + return true; } diff --git a/device/IrisCameraController.h b/device/IrisCameraController.h index 5d7e269..67cbe2f 100644 --- a/device/IrisCameraController.h +++ b/device/IrisCameraController.h @@ -1,11 +1,12 @@ -#ifndef IRISCAMERACONTROLLER_H +#ifndef IRISCAMERACONTROLLER_H #define IRISCAMERACONTROLLER_H #include -#include "IrisCameraCapEventHandler.h" +#include "AcquisitionThread.h" +#include "utils/UtilInclude.h" -class IrisCameraCapEventHandler; +#define ENUMRATE_TIME_OUT 200 class IrisCameraController : public QObject { @@ -14,36 +15,31 @@ explicit IrisCameraController(QObject *parent = nullptr); ~IrisCameraController(); - // 初始化并打开人脸相机 - void initIrisCamera(); void openIrisCamera(); void closeIrisCamera(); void startCapture(); void stopCapture(); - void getLeftAndRightEyeFrame(); + CAcquisitionThread * m_pobjAcqThread; + GX_DEV_HANDLE m_hDevice; ///< Device Handle + uint32_t m_ui32DeviceNum; ///< Device number enumerated - IrisCameraCapEventHandler * irisCamHandler; + bool m_bOpen; ///< Flag : camera is opened or not + bool m_bAcquisitionStart; ///< Flag : camera is acquiring or not private: - GxIAPICPP::gxdeviceinfo_vector irisCamList; - - CGXDevicePointer irisCamPtr; ///< 设备句柄 - - CGXStreamPointer irisStreamPtr; ///< 左眼设备流 - - CGXFeatureControlPointer irisFeaturePtr; ///< 左眼属性控制器 - - CGXFeatureControlPointer irisStreamFeaturePtr; ///< 左眼流层控制器对象 - - void OpenDevice(); + // 初始化并打开人脸相机 + void initIrisCameraController(); + void SetUpAcquisitionThread(); + void UpdateDeviceList(); + bool SetAcquisitionBufferNum(); + void StartAcquisition(); + void StopAcquisition(); signals: - -public slots: - void getOneFaceFrm(); - + void irisCameraInitError(); + void irisCameraTermError(); }; #endif // IRISCAMERACONTROLLER_H diff --git a/device/device.pri b/device/device.pri index d1330a0..583721b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,13 +1,14 @@ HEADERS += $$PWD/IrisCameraController.h -HEADERS += $$PWD/IrisCameraCapEventHandler.h -#HEADERS += $$PWD/iris/IrisRegistProcess.h +#HEADERS += $$PWD/IrisCameraCapEventHandler.h +HEADERS += $$PWD/Common.h +HEADERS += $$PWD/AcquisitionThread.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h SOURCES += $$PWD/IrisCameraController.cpp -SOURCES += $$PWD/IrisCameraCapEventHandler.cpp -#SOURCES += $$PWD/iris/IrisRegistProcess.cpp +#SOURCES += $$PWD/IrisCameraCapEventHandler.cpp +SOURCES += $$PWD/AcquisitionThread.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 38f54fe..e4c8a02 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif @@ -11,7 +11,7 @@ // 连接算法服务 clientUtil = new SocketClientUtil(this); - clientUtil->connect("192.168.83.223", 50007); + clientUtil->connect(SettingConfig::getInstance().DEBUG_SEGMENT_IP, 50007); // 调用socket发送消息 connect(this, &IrisRecogProcess::sendDataToExract, clientUtil, &SocketClientUtil::sendData); @@ -43,18 +43,18 @@ continue; } - // 1. 图像栈中没有图像则直接返回 - if (ProMemory::getInstance().isIrisQueueEmpty() == true) + // 1. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 + if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) { - qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); + qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } - // 2. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 - if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) + // 2. 图像栈中没有图像则直接返回 + if (ProMemory::getInstance().isIrisQueueEmpty() == true) { - qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); + qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } @@ -73,7 +73,7 @@ int findEyeLast = timer.elapsed(); qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); -// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.matData = cv::imread("/home/casic/code/irisLogs/145333.552.bmp", 0); // irisInfo.hasEye = true; // 4.1 没有找到眼睛则返回 @@ -117,11 +117,10 @@ // 缩放到320 * 240 cv::resize(segMat, segMat, cv::Size(SettingConfig::getInstance().IRIS_WIDTH * 0.5, SettingConfig::getInstance().IRIS_HEIGHT * 0.5)); - - // std::string filename = QString("%1\\%2\\%3-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - // cv::imwrite(filename, segMat); - // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - +/* + std::string filename = QString("%1/%2/%3-seg.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + cv::imwrite(filename, segMat); +*/ int segMatSize = segMat.cols * segMat.rows; QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 @@ -167,9 +166,9 @@ // 成功接收后清除缓存区 clientUtil->resetRecvBuffer(); /* - std::string pupilSeg = QString("%1\\%2\\%3-pupil-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string maskSeg = QString("%1\\%2\\%3-mask-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); - std::string irisSeg = QString("%1\\%2\\%3-iris-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string pupilSeg = QString("%1/%2/%3-pupil-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string maskSeg = QString("%1/%2/%3-mask-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); + std::string irisSeg = QString("%1/%2/%3-iris-seg.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); cv::imwrite(pupilSeg, pupil); cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); @@ -196,12 +195,20 @@ CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; irisInfo = casic::iris::CasicIrisInterface::getInstance().irisEncode(irisInfo); /* - std::string codeFilename = QString("%1\\%2\\%3-code.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string codeFilename = QString("%1/%2/%3-code.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); + std::string maskFilename = QString("%1/%2/%3-mask.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); */ + if (irisInfo.postProcSucc == false) { + qDebug() << "算法post process失败,暂停200ms"; + + addOneTryCount(); + this->msleep(THREAD_MSLEEP); // 200ms后再判断 + continue; + } + // 从编码中提取特征值 irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); @@ -211,6 +218,8 @@ CasicIrisRecState::getInstance().extractTmLast = encodeLast; CasicIrisRecState::getInstance().recogTimeLast += encodeLast; +// cv::imwrite(QString("%1/%2/%3.bmp").arg("/home/nvidia/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).toStdString(), irisInfo.matData); + // 开始匹配 timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) @@ -219,7 +228,7 @@ float score = casic::iris::CasicIrisInterface::getInstance().calculatePairPoints(feature.irisFeatureCode, irisInfo.irisFeatureCode); // 计算压缩编码的比较值 -// cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); +// cv::imwrite(QString("%1/%2/%3-%4.bmp").arg("/home/casic/code/irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss.zzz")).arg(score).toStdString(), irisInfo.matData); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; @@ -251,7 +260,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } @@ -268,7 +277,7 @@ CasicIrisRecState::getInstance().tryCount = 0; this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); emit failedMatchedIris(); @@ -290,7 +299,7 @@ // 识别失败时暂停工作 待返回识别界面时再开始工作和拍图 this->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().irisCamCtrl->stopCapture(); ProMemory::getInstance().clearIrisQueue(); } } else if (ProMemory::getInstance().appState == AppConstants::ApplicationState::STATE_WORKING) @@ -298,7 +307,8 @@ CasicIrisRecState::getInstance().noEyeCount++; // 如果在工作状态 则超过一定次数后返回待机 - if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT) + if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT && + SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT > 0) { // 发送信号待机 emit backToLockScreen(); diff --git a/device/iris/IrisRecogProcess.h b/device/iris/IrisRecogProcess.h index 9a3eec6..e21c1a7 100644 --- a/device/iris/IrisRecogProcess.h +++ b/device/iris/IrisRecogProcess.h @@ -1,4 +1,4 @@ -#ifndef IRISRECOGPROCESS_H +#ifndef IRISRECOGPROCESS_H #define IRISRECOGPROCESS_H #define THREAD_MSLEEP 200 @@ -10,6 +10,7 @@ #include "ProMemory.h" #include "device/iris/CasicIrisRecState.h" +#include "casic/iris/CasicIrisInterface.h" class IrisRecogProcess : public QThread { diff --git a/main.cpp b/main.cpp index 9052ddb..3bfb1c6 100644 --- a/main.cpp +++ b/main.cpp @@ -1,11 +1,11 @@ -#include "MainWindowForm.h" - -#include - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - MainWindowForm w; - w.show(); - return a.exec(); -} +#include "MainWindowForm.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindowForm w; + w.show(); + return a.exec(); +} diff --git a/utils/ImageUtil.cpp b/utils/ImageUtil.cpp index ff77331..d40ea79 100644 --- a/utils/ImageUtil.cpp +++ b/utils/ImageUtil.cpp @@ -1,107 +1,107 @@ -#include "ImageUtil.h" - -ImageUtil::ImageUtil() -{ - -} - -QImage ImageUtil::MatImageToQImage(const cv::Mat &src) -{ - //CV_8UC1 8位无符号的单通道---灰度图片 - if(src.type() == CV_8UC1) - { - QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); - return qImage; - } - //为3通道的彩色图片 - else if(src.type() == CV_8UC3) - { - //得到图像的的首地址 - const uchar *pSrc = (const uchar*)src.data; - //以src构造图片 - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); - } - //四通道图片, 带Alpha通道的RGB彩色图像 - else if(src.type() == CV_8UC4) - { - const uchar *pSrc = (const uchar*)src.data; - QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); - //返回图像的子区域作为一个新图像 - return qImage.copy(); - } - else - { - return QImage(); - } -} - -cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) -{ - cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); - return img; -} - -cv::Mat ImageUtil::QImageToMat(QImage image) -{ - cv::Mat mat; - switch(image.format()) - { - case QImage::Format_ARGB32: - case QImage::Format_RGB32: - case QImage::Format_ARGB32_Premultiplied: - mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_RGB888: - mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); - cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); - break; - case QImage::Format_Indexed8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); - break; - case QImage::Format_Grayscale8: - mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); - break; - - default: - break; - } - - mat = mat.clone(); - - return mat; -} - -/* -QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) -{ - QImage qImage(data, width, height, format); - //在不改变实际图像数据的条件下, 交换红蓝通道 - return qImage.rgbSwapped(); -} - -QString ImageUtil::QImageToBase64(QImage image) -{ - QByteArray ba; - QBuffer buf(&ba); - image.save(&buf, "bmp"); - QString base64String = ba.toBase64(); - return base64String; -} - -cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) -{ - cv::Mat matClone = src.clone(); - cv::Rect bigRect; - - bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; - bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; - bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; - bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; - - cv::Mat roi = matClone(bigRect); - - return roi; -} -*/ +#include "ImageUtil.h" + +ImageUtil::ImageUtil() +{ + +} + +QImage ImageUtil::MatImageToQImage(const cv::Mat &src) +{ + //CV_8UC1 8位无符号的单通道---灰度图片 + if(src.type() == CV_8UC1) + { + QImage qImage((const unsigned char *)(src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8); + return qImage; + } + //为3通道的彩色图片 + else if(src.type() == CV_8UC3) + { + //得到图像的的首地址 + const uchar *pSrc = (const uchar*)src.data; + //以src构造图片 + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); + } + //四通道图片, 带Alpha通道的RGB彩色图像 + else if(src.type() == CV_8UC4) + { + const uchar *pSrc = (const uchar*)src.data; + QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32); + //返回图像的子区域作为一个新图像 + return qImage.copy(); + } + else + { + return QImage(); + } +} + +cv::Mat ImageUtil::ucharToMat(unsigned char *data, int row, int col) +{ + cv::Mat img(row, col, CV_8UC1, (unsigned char *)data); + return img; +} + +cv::Mat ImageUtil::QImageToMat(QImage image) +{ + cv::Mat mat; + switch(image.format()) + { + case QImage::Format_ARGB32: + case QImage::Format_RGB32: + case QImage::Format_ARGB32_Premultiplied: + mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_RGB888: + mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); + cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); + break; + case QImage::Format_Indexed8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); + break; + case QImage::Format_Grayscale8: + mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine()); + break; + + default: + break; + } + + mat = mat.clone(); + + return mat; +} + +/* +QImage ImageUtil::UcharToQImage(unsigned char* data, int width, int height, QImage::Format format) +{ + QImage qImage(data, width, height, format); + //在不改变实际图像数据的条件下, 交换红蓝通道 + return qImage.rgbSwapped(); +} + +QString ImageUtil::QImageToBase64(QImage image) +{ + QByteArray ba; + QBuffer buf(&ba); + image.save(&buf, "bmp"); + QString base64String = ba.toBase64(); + return base64String; +} + +cv::Mat ImageUtil::MatImageRect(const cv::Mat &src, cv::Rect rect, int delta) +{ + cv::Mat matClone = src.clone(); + cv::Rect bigRect; + + bigRect.x = rect.x - delta < 0 ? 0 : rect.x - delta; + bigRect.y = rect.y - delta < 0 ? 0 : rect.y - delta; + bigRect.width = rect.x + rect.width + 2 * delta > src.cols ? src.cols - rect.x : rect.width + 2 * delta; + bigRect.height = rect.y + rect.height + 2 * delta > src.rows ? src.rows - rect.y : rect.height + 2 * delta; + + cv::Mat roi = matClone(bigRect); + + return roi; +} +*/ diff --git a/utils/ImageUtil.h b/utils/ImageUtil.h index d9bf00a..4b702f4 100644 --- a/utils/ImageUtil.h +++ b/utils/ImageUtil.h @@ -1,23 +1,23 @@ -#ifndef IMAGEUTIL_H -#define IMAGEUTIL_H - -#include -#include -#include "opencv2/opencv.hpp" - -class ImageUtil -{ -public: - ImageUtil(); - - static QImage MatImageToQImage(const cv::Mat &src); -// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); - - static cv::Mat ucharToMat(unsigned char * data, int row, int col); - static cv::Mat QImageToMat(QImage image); -// static QString QImageToBase64(QImage image); - -// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); -}; - -#endif // IMAGEUTIL_H +#ifndef IMAGEUTIL_H +#define IMAGEUTIL_H + +#include +#include +#include "opencv2/opencv.hpp" + +class ImageUtil +{ +public: + ImageUtil(); + + static QImage MatImageToQImage(const cv::Mat &src); +// static QImage UcharToQImage(unsigned char* data, int width, int height, QImage::Format format); + + static cv::Mat ucharToMat(unsigned char * data, int row, int col); + static cv::Mat QImageToMat(QImage image); +// static QString QImageToBase64(QImage image); + +// static cv::Mat MatImageRect(const cv::Mat &src, cv::Rect rect, int delta); +}; + +#endif // IMAGEUTIL_H diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp index 663db0f..05c4c68 100644 --- a/utils/SettingConfig.cpp +++ b/utils/SettingConfig.cpp @@ -1,4 +1,4 @@ -#include "SettingConfig.h" +#include "SettingConfig.h" #include SettingConfig::SettingConfig() @@ -34,6 +34,9 @@ LOG_FILE = getProperty("log", "logFile").toString(); LOG_LEVEL = getProperty("log", "logLevel").toString(); + + DEBUG_CAMERA_ROTATE = getProperty("debug", "cameraRotate").toString(); + DEBUG_SEGMENT_IP = getProperty("debug", "segmentIp").toString(); } diff --git a/utils/SettingConfig.h b/utils/SettingConfig.h index b65f553..c35d6ab 100644 --- a/utils/SettingConfig.h +++ b/utils/SettingConfig.h @@ -1,4 +1,4 @@ -#ifndef SETTINGCONFIG_H +#ifndef SETTINGCONFIG_H #define SETTINGCONFIG_H #include @@ -55,6 +55,9 @@ QString LOG_FILE; QString LOG_LEVEL; + QString DEBUG_CAMERA_ROTATE; + QString DEBUG_SEGMENT_IP; + private: SettingConfig(); diff --git a/utils/SocketClientUtil.cpp b/utils/SocketClientUtil.cpp index d539d64..20b8869 100644 --- a/utils/SocketClientUtil.cpp +++ b/utils/SocketClientUtil.cpp @@ -1,9 +1,10 @@ -#include "SocketClientUtil.h" +#include "SocketClientUtil.h" #include "utils/ByteUtil.h" SocketClientUtil::SocketClientUtil(QObject *parent) : QObject(parent) { QObject::connect(&objClient, &QTcpSocket::readyRead, this, &SocketClientUtil::readData); + QObject::connect(&objClient, &QTcpSocket::disconnected, this, &SocketClientUtil::socketReconnect); } void SocketClientUtil::connect(QString host, int port) @@ -16,6 +17,10 @@ void SocketClientUtil::closeConnect() { + QObject::disconnect(&objClient, &QTcpSocket::readyRead, this, &SocketClientUtil::readData); + QObject::disconnect(&objClient, &QTcpSocket::disconnected, this, &SocketClientUtil::socketReconnect); + + objClient.disconnectFromHost(); objClient.close(); } @@ -45,3 +50,9 @@ emit this->responseReaded(); } } + +void SocketClientUtil::socketReconnect() +{ + objClient.close(); + objClient.connectToHost(this->host, this->port); +} diff --git a/utils/SocketClientUtil.h b/utils/SocketClientUtil.h index 96b60e0..8bd1b8c 100644 --- a/utils/SocketClientUtil.h +++ b/utils/SocketClientUtil.h @@ -1,4 +1,4 @@ -#ifndef SOCKETCLIENTUTIL_H +#ifndef SOCKETCLIENTUTIL_H #define SOCKETCLIENTUTIL_H #include @@ -30,6 +30,7 @@ public slots: void readData(); void sendData(QByteArray data); + void socketReconnect(); }; diff --git a/utils/TimeCounterUtil.cpp b/utils/TimeCounterUtil.cpp index 275945f..78c3d69 100644 --- a/utils/TimeCounterUtil.cpp +++ b/utils/TimeCounterUtil.cpp @@ -1,8 +1,9 @@ -#include "TimeCounterUtil.h" - -TimeCounterUtil::TimeCounterUtil() -{ - faceCapCounter = new QTimer(); - irisCapCounter = new QTimer(); - clockCounter = new QTimer(); -} +#include "TimeCounterUtil.h" + +TimeCounterUtil::TimeCounterUtil() +{ + faceCapCounter = new QTimer(); + irisCapCounter = new QTimer(); + clockCounter = new QTimer(); + videoCounter = new QTimer(); +} diff --git a/utils/TimeCounterUtil.h b/utils/TimeCounterUtil.h index 28b29f1..91f8da0 100644 --- a/utils/TimeCounterUtil.h +++ b/utils/TimeCounterUtil.h @@ -1,29 +1,30 @@ -#ifndef TIMECOUNTERUTIL_H -#define TIMECOUNTERUTIL_H - -#include -#include - -class TimeCounterUtil : public QObject -{ -public: - - ~TimeCounterUtil() {}; - TimeCounterUtil(const TimeCounterUtil&)=delete; - TimeCounterUtil& operator=(const TimeCounterUtil&)=delete; - - static TimeCounterUtil& getInstance() { - static TimeCounterUtil instance; - return instance; - } - - QTimer * faceCapCounter; - QTimer * irisCapCounter; - QTimer * clockCounter; - -private: - TimeCounterUtil(); - -}; - -#endif // TIMECOUNTERUTIL_H +#ifndef TIMECOUNTERUTIL_H +#define TIMECOUNTERUTIL_H + +#include +#include + +class TimeCounterUtil : public QObject +{ +public: + + ~TimeCounterUtil() {}; + TimeCounterUtil(const TimeCounterUtil&)=delete; + TimeCounterUtil& operator=(const TimeCounterUtil&)=delete; + + static TimeCounterUtil& getInstance() { + static TimeCounterUtil instance; + return instance; + } + + QTimer * faceCapCounter; + QTimer * irisCapCounter; + QTimer * clockCounter; + QTimer * videoCounter; // show video images on main window + +private: + TimeCounterUtil(); + +}; + +#endif // TIMECOUNTERUTIL_H diff --git a/utils/UtilInclude.h b/utils/UtilInclude.h index 0b329c9..bea17be 100644 --- a/utils/UtilInclude.h +++ b/utils/UtilInclude.h @@ -1,15 +1,15 @@ -#ifndef UTILINCLUDE_H -#define UTILINCLUDE_H - -#include -#include "ByteUtil.h" -#include "ImageUtil.h" -#include "LogUtil.h" -#include "SettingConfig.h" -#include "SocketClientUtil.h" -#include "SpeakerUtil.h" -#include "TimeCounterUtil.h" -//#include "UDPClientUtil.h" -//#include "HttpRequestUtil.h" - -#endif // UTILINCLUDE_H +#ifndef UTILINCLUDE_H +#define UTILINCLUDE_H + +#include +#include "ByteUtil.h" +#include "ImageUtil.h" +#include "LogUtil.h" +#include "SettingConfig.h" +#include "SocketClientUtil.h" +#include "SpeakerUtil.h" +#include "TimeCounterUtil.h" +//#include "UDPClientUtil.h" +//#include "HttpRequestUtil.h" + +#endif // UTILINCLUDE_H diff --git a/utils/id/IdWorker.h b/utils/id/IdWorker.h index 6c48aa9..079bbcb 100644 --- a/utils/id/IdWorker.h +++ b/utils/id/IdWorker.h @@ -1,218 +1,218 @@ -#ifndef _JW_CORE_ID_WORKER_H_ -#define _JW_CORE_ID_WORKER_H_ - -#include -#include -#include -#include -#include -#include "Noncopyable.h" -#include "Singleton.h" - -// 如果不使用 mutex, 则开启下面这个定义, 但是我发现, 还是开启 mutex 功能, 速度比较快 -// #define SNOWFLAKE_ID_WORKER_NO_LOCK - -namespace Jiawa { - - /** - * @brief 核心 - * 核心功能 - */ - namespace Core { - - /** - * @brief 分布式id生成类 - * https://segmentfault.com/a/1190000011282426 - * https://github.com/twitter/snowflake/blob/snowflake-2010/src/main/scala/com/twitter/service/snowflake/IdWorker.scala - * - * 64bit id: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 - * || || || | | | - * |└---------------------------时间戳--------------------------┘└中心-┘└机器-┘ └----序列号----┘ - * | - * 不用 - * SnowFlake的优点: 整体上按照时间自增排序, 并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分), 并且效率较高, 经测试, SnowFlake每秒能够产生26万ID左右. - */ - class SnowflakeIdWorker : private Noncopyable { - - // 实现单例 - friend class Singleton; - - public: - typedef unsigned int UInt; - typedef unsigned long long int UInt64; - -#ifdef SNOWFLAKE_ID_WORKER_NO_LOCK - typedef std::atomic AtomicUInt; - typedef std::atomic AtomicUInt64; -#else - typedef UInt AtomicUInt; - typedef UInt64 AtomicUInt64; -#endif - - void setWorkerId(UInt workerId) { - this->workerId = workerId; - } - - void setDatacenterId(UInt datacenterId) { - this->datacenterId = datacenterId; - } - - UInt64 getId() { - return nextId(); - } - - /** - * 获得下一个ID (该方法是线程安全的) - * - * @return SnowflakeId - */ - UInt64 nextId() { -#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK - std::unique_lock lock{ mutex }; - AtomicUInt64 timestamp{ 0 }; -#else - static AtomicUInt64 timestamp{ 0 }; -#endif - timestamp = timeGen(); - - // 如果当前时间小于上一次ID生成的时间戳, 说明系统时钟回退过这个时候应当抛出异常 - if (timestamp < lastTimestamp) { - std::ostringstream s; - s << "clock moved backwards. Refusing to generate id for " << lastTimestamp - timestamp << " milliseconds"; - throw std::exception(std::runtime_error(s.str())); - } - - if (lastTimestamp == timestamp) { - // 如果是同一时间生成的, 则进行毫秒内序列 - sequence = (sequence + 1) & sequenceMask; - if (0 == sequence) { - // 毫秒内序列溢出, 阻塞到下一个毫秒,获得新的时间戳 - timestamp = tilNextMillis(lastTimestamp); - } - } else { - sequence = 0; - } - -#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK - lastTimestamp = timestamp; -#else - lastTimestamp = timestamp.load(); -#endif - - // 移位并通过或运算拼到一起组成64位的ID - return ((timestamp - twepoch) << timestampLeftShift) - | (datacenterId << datacenterIdShift) - | (workerId << workerIdShift) - | sequence; - } - - protected: - SnowflakeIdWorker() : workerId(0), datacenterId(0), sequence(0), lastTimestamp(0) { } - - /** - * 返回以毫秒为单位的当前时间 - * - * @return 当前时间(毫秒) - */ - UInt64 timeGen() const { - auto t = std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()); - return t.time_since_epoch().count(); - } - - /** - * 阻塞到下一个毫秒, 直到获得新的时间戳 - * - * @param lastTimestamp 上次生成ID的时间截 - * @return 当前时间戳 - */ - UInt64 tilNextMillis(UInt64 lastTimestamp) const { - UInt64 timestamp = timeGen(); - while (timestamp <= lastTimestamp) { - timestamp = timeGen(); - } - return timestamp; - } - - private: - -#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK - std::mutex mutex; -#endif - - /** - * 开始时间截 (2018-01-01 00:00:00.000) - */ - const UInt64 twepoch = 1514736000000; - - /** - * 机器id所占的位数 - */ - const UInt workerIdBits = 5; - - /** - * 数据中心id所占的位数 - */ - const UInt datacenterIdBits = 5; - - /** - * 序列所占的位数 - */ - const UInt sequenceBits = 12; - - /** - * 机器ID向左移12位 - */ - const UInt workerIdShift = sequenceBits; - - /** - * 数据标识id向左移17位 - */ - const UInt datacenterIdShift = workerIdShift + workerIdBits; - - /** - * 时间截向左移22位 - */ - const UInt timestampLeftShift = datacenterIdShift + datacenterIdBits; - - /** - * 支持的最大机器id, 结果是31 - */ - const UInt maxWorkerId = -1 ^ (-1 << workerIdBits); - - /** - * 支持的最大数据中心id, 结果是31 - */ - const UInt maxDatacenterId = -1 ^ (-1 << datacenterIdBits); - - /** - * 生成序列的掩码, 这里为4095 - */ - const UInt sequenceMask = -1 ^ (-1 << sequenceBits); - - /** - * 工作机器id(0~31) - */ - UInt workerId; - - /** - * 数据中心id(0~31) - */ - UInt datacenterId; - - /** - * 毫秒内序列(0~4095) - */ - AtomicUInt sequence{ 0 }; - - /** - * 上次生成ID的时间截 - */ - AtomicUInt64 lastTimestamp{ 0 }; - - }; - - typedef SnowflakeIdWorker IdWorker; - } -} - -#endif // _JW_CORE_ID_WORKER_H_ +#ifndef _JW_CORE_ID_WORKER_H_ +#define _JW_CORE_ID_WORKER_H_ + +#include +#include +#include +#include +#include +#include "Noncopyable.h" +#include "Singleton.h" + +// 如果不使用 mutex, 则开启下面这个定义, 但是我发现, 还是开启 mutex 功能, 速度比较快 +// #define SNOWFLAKE_ID_WORKER_NO_LOCK + +namespace Jiawa { + + /** + * @brief 核心 + * 核心功能 + */ + namespace Core { + + /** + * @brief 分布式id生成类 + * https://segmentfault.com/a/1190000011282426 + * https://github.com/twitter/snowflake/blob/snowflake-2010/src/main/scala/com/twitter/service/snowflake/IdWorker.scala + * + * 64bit id: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + * || || || | | | + * |└---------------------------时间戳--------------------------┘└中心-┘└机器-┘ └----序列号----┘ + * | + * 不用 + * SnowFlake的优点: 整体上按照时间自增排序, 并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分), 并且效率较高, 经测试, SnowFlake每秒能够产生26万ID左右. + */ + class SnowflakeIdWorker : private Noncopyable { + + // 实现单例 + friend class Singleton; + + public: + typedef unsigned int UInt; + typedef unsigned long long int UInt64; + +#ifdef SNOWFLAKE_ID_WORKER_NO_LOCK + typedef std::atomic AtomicUInt; + typedef std::atomic AtomicUInt64; +#else + typedef UInt AtomicUInt; + typedef UInt64 AtomicUInt64; +#endif + + void setWorkerId(UInt workerId) { + this->workerId = workerId; + } + + void setDatacenterId(UInt datacenterId) { + this->datacenterId = datacenterId; + } + + UInt64 getId() { + return nextId(); + } + + /** + * 获得下一个ID (该方法是线程安全的) + * + * @return SnowflakeId + */ + UInt64 nextId() { +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + std::unique_lock lock{ mutex }; + AtomicUInt64 timestamp{ 0 }; +#else + static AtomicUInt64 timestamp{ 0 }; +#endif + timestamp = timeGen(); + + // 如果当前时间小于上一次ID生成的时间戳, 说明系统时钟回退过这个时候应当抛出异常 + if (timestamp < lastTimestamp) { + std::ostringstream s; + s << "clock moved backwards. Refusing to generate id for " << lastTimestamp - timestamp << " milliseconds"; + throw std::exception(std::runtime_error(s.str())); + } + + if (lastTimestamp == timestamp) { + // 如果是同一时间生成的, 则进行毫秒内序列 + sequence = (sequence + 1) & sequenceMask; + if (0 == sequence) { + // 毫秒内序列溢出, 阻塞到下一个毫秒,获得新的时间戳 + timestamp = tilNextMillis(lastTimestamp); + } + } else { + sequence = 0; + } + +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + lastTimestamp = timestamp; +#else + lastTimestamp = timestamp.load(); +#endif + + // 移位并通过或运算拼到一起组成64位的ID + return ((timestamp - twepoch) << timestampLeftShift) + | (datacenterId << datacenterIdShift) + | (workerId << workerIdShift) + | sequence; + } + + protected: + SnowflakeIdWorker() : workerId(0), datacenterId(0), sequence(0), lastTimestamp(0) { } + + /** + * 返回以毫秒为单位的当前时间 + * + * @return 当前时间(毫秒) + */ + UInt64 timeGen() const { + auto t = std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()); + return t.time_since_epoch().count(); + } + + /** + * 阻塞到下一个毫秒, 直到获得新的时间戳 + * + * @param lastTimestamp 上次生成ID的时间截 + * @return 当前时间戳 + */ + UInt64 tilNextMillis(UInt64 lastTimestamp) const { + UInt64 timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + private: + +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + std::mutex mutex; +#endif + + /** + * 开始时间截 (2018-01-01 00:00:00.000) + */ + const UInt64 twepoch = 1514736000000; + + /** + * 机器id所占的位数 + */ + const UInt workerIdBits = 5; + + /** + * 数据中心id所占的位数 + */ + const UInt datacenterIdBits = 5; + + /** + * 序列所占的位数 + */ + const UInt sequenceBits = 12; + + /** + * 机器ID向左移12位 + */ + const UInt workerIdShift = sequenceBits; + + /** + * 数据标识id向左移17位 + */ + const UInt datacenterIdShift = workerIdShift + workerIdBits; + + /** + * 时间截向左移22位 + */ + const UInt timestampLeftShift = datacenterIdShift + datacenterIdBits; + + /** + * 支持的最大机器id, 结果是31 + */ + const UInt maxWorkerId = -1 ^ (-1 << workerIdBits); + + /** + * 支持的最大数据中心id, 结果是31 + */ + const UInt maxDatacenterId = -1 ^ (-1 << datacenterIdBits); + + /** + * 生成序列的掩码, 这里为4095 + */ + const UInt sequenceMask = -1 ^ (-1 << sequenceBits); + + /** + * 工作机器id(0~31) + */ + UInt workerId; + + /** + * 数据中心id(0~31) + */ + UInt datacenterId; + + /** + * 毫秒内序列(0~4095) + */ + AtomicUInt sequence{ 0 }; + + /** + * 上次生成ID的时间截 + */ + AtomicUInt64 lastTimestamp{ 0 }; + + }; + + typedef SnowflakeIdWorker IdWorker; + } +} + +#endif // _JW_CORE_ID_WORKER_H_ diff --git a/utils/id/Noncopyable.h b/utils/id/Noncopyable.h index d87f58a..4fc555a 100644 --- a/utils/id/Noncopyable.h +++ b/utils/id/Noncopyable.h @@ -1,31 +1,31 @@ -#ifndef _JW_CORE_NONCOPYABLE_H_ -#define _JW_CORE_NONCOPYABLE_H_ - - -// Private copy constructor and copy assignment ensure classes derived from -// class noncopyable cannot be copied. - -namespace Jiawa { - namespace Core { - - // protection from unintended ADL(Argument Dependent Lookup) - namespace Noncopyable_ { - - class Noncopyable - { - protected: - Noncopyable() = default; - ~Noncopyable() = default; - - Noncopyable(const Noncopyable&) = delete; - Noncopyable(const Noncopyable&&) = delete; - Noncopyable& operator=(const Noncopyable&) = delete; - Noncopyable& operator=(const Noncopyable&&) = delete; - }; - } - - typedef Noncopyable_::Noncopyable Noncopyable; - } -} - -#endif // _JW_CORE_NONCOPYABLE_H_ +#ifndef _JW_CORE_NONCOPYABLE_H_ +#define _JW_CORE_NONCOPYABLE_H_ + + +// Private copy constructor and copy assignment ensure classes derived from +// class noncopyable cannot be copied. + +namespace Jiawa { + namespace Core { + + // protection from unintended ADL(Argument Dependent Lookup) + namespace Noncopyable_ { + + class Noncopyable + { + protected: + Noncopyable() = default; + ~Noncopyable() = default; + + Noncopyable(const Noncopyable&) = delete; + Noncopyable(const Noncopyable&&) = delete; + Noncopyable& operator=(const Noncopyable&) = delete; + Noncopyable& operator=(const Noncopyable&&) = delete; + }; + } + + typedef Noncopyable_::Noncopyable Noncopyable; + } +} + +#endif // _JW_CORE_NONCOPYABLE_H_ diff --git a/utils/id/Singleton.h b/utils/id/Singleton.h index d1c0553..daad45c 100644 --- a/utils/id/Singleton.h +++ b/utils/id/Singleton.h @@ -1,60 +1,60 @@ -#ifndef _JW_CORE_SINGLETON_H_ -#define _JW_CORE_SINGLETON_H_ - -namespace Jiawa { - namespace Core { - - // boost/container/detail/singleton.hpp - // http://blog.csdn.net/fullsail/article/details/8483106 - // T must be: no-throw default constructible and no-throw destructible - template - class Singleton { - private: - Singleton() = default; - ~Singleton() = default; - - private: - struct object_creator - { - // This constructor does nothing more than ensure that instance() - // is called before main() begins, thus creating the static - // T object before multithreading race issues can come up. - object_creator() { Singleton::instance(); } - inline void do_nothing() const { } - }; - static object_creator create_object; - - private: - Singleton(const Singleton&) = delete; - Singleton(const Singleton&&) = delete; - Singleton& operator=(const Singleton&) = delete; - Singleton& operator=(const Singleton&&) = delete; - - public: - typedef T object_type; - - // If, at any point (in user code), Singleton::instance() - // is called, then the following function is instantiated. - static object_type& instance() - { - // This is the object that we return a reference to. - // It is guaranteed to be created before main() begins because of - // the next line. - static object_type obj; - - // The following line does nothing else than force the instantiation - // of Singleton::create_object, whose constructor is - // called before main() begins. - create_object.do_nothing(); - - return obj; - } - }; - - template - typename Singleton::object_creator Singleton::create_object; - } -} - -#endif // _JW_CORE_SINGLETON_H_ - +#ifndef _JW_CORE_SINGLETON_H_ +#define _JW_CORE_SINGLETON_H_ + +namespace Jiawa { + namespace Core { + + // boost/container/detail/singleton.hpp + // http://blog.csdn.net/fullsail/article/details/8483106 + // T must be: no-throw default constructible and no-throw destructible + template + class Singleton { + private: + Singleton() = default; + ~Singleton() = default; + + private: + struct object_creator + { + // This constructor does nothing more than ensure that instance() + // is called before main() begins, thus creating the static + // T object before multithreading race issues can come up. + object_creator() { Singleton::instance(); } + inline void do_nothing() const { } + }; + static object_creator create_object; + + private: + Singleton(const Singleton&) = delete; + Singleton(const Singleton&&) = delete; + Singleton& operator=(const Singleton&) = delete; + Singleton& operator=(const Singleton&&) = delete; + + public: + typedef T object_type; + + // If, at any point (in user code), Singleton::instance() + // is called, then the following function is instantiated. + static object_type& instance() + { + // This is the object that we return a reference to. + // It is guaranteed to be created before main() begins because of + // the next line. + static object_type obj; + + // The following line does nothing else than force the instantiation + // of Singleton::create_object, whose constructor is + // called before main() begins. + create_object.do_nothing(); + + return obj; + } + }; + + template + typename Singleton::object_creator Singleton::create_object; + } +} + +#endif // _JW_CORE_SINGLETON_H_ + diff --git a/utils/id/Timer.h b/utils/id/Timer.h index 0f1ff1b..4b2967f 100644 --- a/utils/id/Timer.h +++ b/utils/id/Timer.h @@ -1,57 +1,57 @@ -#ifndef _JW_CORE_TIMER_H_ -#define _JW_CORE_TIMER_H_ - -#include - -namespace Jiawa { - - /** - * @brief 核心 - * 核心功能 - */ - namespace Core { - - /** - * @brief 计时器类 - * 计时 - */ - template - class Timer { - public: - - typedef CLOCK clock; - typedef typename CLOCK::rep rep; - typedef typename CLOCK::duration duration; - typedef typename CLOCK::time_point time_point; - - Timer() : m_start(CLOCK::now()) { - } - - /** - * @brief 重置计时器 - * - * @return 开始的时间点 - */ - time_point reset() { - m_start = CLOCK::now(); - return m_start; - } - - /** - * @brief 得到流逝的时间 - * @param UNIT 返回时间的类型 - * - * @return 返回流逝的时间 - */ - template - typename UNIT::duration::rep elapsed() const { - return std::chrono::duration_cast(CLOCK::now() - m_start).count(); - } - - private: - time_point m_start; - }; - } -} - +#ifndef _JW_CORE_TIMER_H_ +#define _JW_CORE_TIMER_H_ + +#include + +namespace Jiawa { + + /** + * @brief 核心 + * 核心功能 + */ + namespace Core { + + /** + * @brief 计时器类 + * 计时 + */ + template + class Timer { + public: + + typedef CLOCK clock; + typedef typename CLOCK::rep rep; + typedef typename CLOCK::duration duration; + typedef typename CLOCK::time_point time_point; + + Timer() : m_start(CLOCK::now()) { + } + + /** + * @brief 重置计时器 + * + * @return 开始的时间点 + */ + time_point reset() { + m_start = CLOCK::now(); + return m_start; + } + + /** + * @brief 得到流逝的时间 + * @param UNIT 返回时间的类型 + * + * @return 返回流逝的时间 + */ + template + typename UNIT::duration::rep elapsed() const { + return std::chrono::duration_cast(CLOCK::now() - m_start).count(); + } + + private: + time_point m_start; + }; + } +} + #endif // _JW_CORE_TIMER_H_ \ No newline at end of file diff --git a/utils/utils.pri b/utils/utils.pri index 39294b1..bc84cae 100644 --- a/utils/utils.pri +++ b/utils/utils.pri @@ -1,28 +1,28 @@ - -HEADERS += $$PWD/UtilInclude.h - -HEADERS += $$PWD/id/IdWorker.h -HEADERS += $$PWD/id/Noncopyable.h -HEADERS += $$PWD/id/Singleton.h -HEADERS += $$PWD/id/Timer.h - -HEADERS += $$PWD/ImageUtil.h -SOURCES += $$PWD/ImageUtil.cpp - -HEADERS += $$PWD/LogUtil.h - -HEADERS += $$PWD/SettingConfig.h -SOURCES += $$PWD/SettingConfig.cpp - -HEADERS += $$PWD/TimeCounterUtil.h -SOURCES += $$PWD/TimeCounterUtil.cpp - -HEADERS += $$PWD/SpeakerUtil.h -SOURCES += $$PWD/SpeakerUtil.cpp - -HEADERS += $$PWD/SocketClientUtil.h -SOURCES += $$PWD/SocketClientUtil.cpp - -HEADERS += $$PWD/ByteUtil.h -SOURCES += $$PWD/ByteUtil.cpp - + +HEADERS += $$PWD/UtilInclude.h + +HEADERS += $$PWD/id/IdWorker.h +HEADERS += $$PWD/id/Noncopyable.h +HEADERS += $$PWD/id/Singleton.h +HEADERS += $$PWD/id/Timer.h + +HEADERS += $$PWD/ImageUtil.h +SOURCES += $$PWD/ImageUtil.cpp + +HEADERS += $$PWD/LogUtil.h + +HEADERS += $$PWD/SettingConfig.h +SOURCES += $$PWD/SettingConfig.cpp + +HEADERS += $$PWD/TimeCounterUtil.h +SOURCES += $$PWD/TimeCounterUtil.cpp + +HEADERS += $$PWD/SpeakerUtil.h +SOURCES += $$PWD/SpeakerUtil.cpp + +HEADERS += $$PWD/SocketClientUtil.h +SOURCES += $$PWD/SocketClientUtil.cpp + +HEADERS += $$PWD/ByteUtil.h +SOURCES += $$PWD/ByteUtil.cpp +