diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index 1558461..c528381 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -87,9 +87,6 @@ this->cascade->load(cascadeName); } - QElapsedTimer timer; - timer.start(); - std::vector rect; cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); @@ -111,8 +108,8 @@ // .arg(timer.elapsed()).arg(rect.size()) // .arg(rect.at(0).x).arg(rect.at(0).y) // .arg(rect.at(0).width).arg(rect.at(0).height).toStdString()); - qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]") - .arg(timer.elapsed()).arg(rect.size()) + qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]") + .arg(rect.size()) .arg(rect.at(0).x).arg(rect.at(0).y) .arg(rect.at(0).width).arg(rect.at(0).height); @@ -141,20 +138,18 @@ } // 裁剪眼部图像 - cv::Mat halfSize = irisInfo.matData.clone(); - halfSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, + cv::Mat cutSize = irisInfo.matData.clone(); + cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5, SettingConfig::getInstance().IRIS_WIDTH * cutRatio, SettingConfig::getInstance().IRIS_HEIGHT * cutRatio)); - cv::resize(halfSize, halfSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); - cv::flip(halfSize, halfSize, 1); // 左右翻转 + // 裁剪后放大到 640 * 480 + cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); + cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; -// irisInfo.eyeRect = rect.at(0); - - irisInfo.matData = halfSize; -// irisInfo.data = ImageUtil::MatImageToQImage(halfSize); + irisInfo.matData = cutSize; return irisInfo; } @@ -229,9 +224,18 @@ return irisInfo; } +QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo) +{ + QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm); + return irisFeatureCode; +} + float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo) { -// cv::imshow("info", irisInfo.irisCode); -// cv::waitKey(0); return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm); } + +float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other) +{ + return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data())); +} diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index 1558461..c528381 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -87,9 +87,6 @@ this->cascade->load(cascadeName); } - QElapsedTimer timer; - timer.start(); - std::vector rect; cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); @@ -111,8 +108,8 @@ // .arg(timer.elapsed()).arg(rect.size()) // .arg(rect.at(0).x).arg(rect.at(0).y) // .arg(rect.at(0).width).arg(rect.at(0).height).toStdString()); - qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]") - .arg(timer.elapsed()).arg(rect.size()) + qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]") + .arg(rect.size()) .arg(rect.at(0).x).arg(rect.at(0).y) .arg(rect.at(0).width).arg(rect.at(0).height); @@ -141,20 +138,18 @@ } // 裁剪眼部图像 - cv::Mat halfSize = irisInfo.matData.clone(); - halfSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, + cv::Mat cutSize = irisInfo.matData.clone(); + cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5, SettingConfig::getInstance().IRIS_WIDTH * cutRatio, SettingConfig::getInstance().IRIS_HEIGHT * cutRatio)); - cv::resize(halfSize, halfSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); - cv::flip(halfSize, halfSize, 1); // 左右翻转 + // 裁剪后放大到 640 * 480 + cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); + cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; -// irisInfo.eyeRect = rect.at(0); - - irisInfo.matData = halfSize; -// irisInfo.data = ImageUtil::MatImageToQImage(halfSize); + irisInfo.matData = cutSize; return irisInfo; } @@ -229,9 +224,18 @@ return irisInfo; } +QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo) +{ + QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm); + return irisFeatureCode; +} + float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo) { -// cv::imshow("info", irisInfo.irisCode); -// cv::waitKey(0); return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm); } + +float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other) +{ + return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data())); +} diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index cbee8fe..26fbedc 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -27,7 +27,9 @@ CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); + QByteArray extractFeature(CasicIrisInfo irisInfo); float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo); + float calculatePairPoints(QByteArray feature, QByteArray other); void setCascadeFile(QString filename); void setMinEyeSize(int minEyeSize); diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index 1558461..c528381 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -87,9 +87,6 @@ this->cascade->load(cascadeName); } - QElapsedTimer timer; - timer.start(); - std::vector rect; cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); @@ -111,8 +108,8 @@ // .arg(timer.elapsed()).arg(rect.size()) // .arg(rect.at(0).x).arg(rect.at(0).y) // .arg(rect.at(0).width).arg(rect.at(0).height).toStdString()); - qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]") - .arg(timer.elapsed()).arg(rect.size()) + qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]") + .arg(rect.size()) .arg(rect.at(0).x).arg(rect.at(0).y) .arg(rect.at(0).width).arg(rect.at(0).height); @@ -141,20 +138,18 @@ } // 裁剪眼部图像 - cv::Mat halfSize = irisInfo.matData.clone(); - halfSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, + cv::Mat cutSize = irisInfo.matData.clone(); + cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5, SettingConfig::getInstance().IRIS_WIDTH * cutRatio, SettingConfig::getInstance().IRIS_HEIGHT * cutRatio)); - cv::resize(halfSize, halfSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); - cv::flip(halfSize, halfSize, 1); // 左右翻转 + // 裁剪后放大到 640 * 480 + cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); + cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; -// irisInfo.eyeRect = rect.at(0); - - irisInfo.matData = halfSize; -// irisInfo.data = ImageUtil::MatImageToQImage(halfSize); + irisInfo.matData = cutSize; return irisInfo; } @@ -229,9 +224,18 @@ return irisInfo; } +QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo) +{ + QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm); + return irisFeatureCode; +} + float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo) { -// cv::imshow("info", irisInfo.irisCode); -// cv::waitKey(0); return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm); } + +float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other) +{ + return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data())); +} diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index cbee8fe..26fbedc 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -27,7 +27,9 @@ CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); + QByteArray extractFeature(CasicIrisInfo irisInfo); float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo); + float calculatePairPoints(QByteArray feature, QByteArray other); void setCascadeFile(QString filename); void setMinEyeSize(int minEyeSize); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index c8ffe3e..ad456b4 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -177,6 +177,8 @@ // Get the coordinates file >> i; file >> j; + mvApplicationPoints.push_back(QPair(i, j)); + // Set pixel to "on" if (i < 0 || i > applicationPoints.rows - 1 || j < 0 || j > applicationPoints.cols- 1) { @@ -237,7 +239,96 @@ roi.copyTo(dst); //cv::copyTo(img2, dst, NULL); } - return encodeImage; + cv::Mat image8UC1; + encodeImage.convertTo(image8UC1, CV_8UC1); + return image8UC1; +} + +QByteArray CasicIrisRec::extractFeature(cv::Mat irisCode, cv::Mat maskNorm) +{ + // count points width and height + cv::Mat pointTemp(applicationPoints); + cv::Mat rowTemp; + + std::vector pointRows; + for (int i = 0; i < applicationPoints.rows; i++) { + rowTemp = pointTemp(cv::Rect(0, i, applicationPoints.cols, 1)); + if (cv::sum(rowTemp)[0] > 0) { + pointRows.push_back(i); + } + } + + int width = irisCode.cols; + int height = pointRows.size(); + rowTemp.release(); + pointTemp.release(); + + int n_codes = irisCode.rows / applicationPoints.rows; + + int irisDataLength = (n_codes + 1) * width * height; + uchar * irisData = new uchar[irisDataLength]; + int irisDataIndex = 0; + + uchar* codePixel = new uchar; + + // save iris code 512 * 8 * 6 + for (int n = 0; n < n_codes; n++) { // 6 + for (auto i : pointRows) { // 8 + i = n * maskNorm.rows + i; + for (int j = 0; j < irisCode.cols; j++) { // 512 + codePixel = (uchar*)(irisCode.data + i * irisCode.step + j); + if (*codePixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *codePixel; + } + } + } + } + + // save iris mask 512 * 8 * 1 + uchar * maskPixel; + for (auto i : pointRows) { // 8 + for (int j = 0; j < irisCode.cols; j++) { // 512 + maskPixel = (uchar*)(maskNorm.data + i * maskNorm.step + j); + if (*maskPixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *maskPixel; + } + } + } + + + uchar * irisFeaturePtr = new uchar[irisDataLength / 8 + 5]; + memset(irisFeaturePtr, 0, irisDataLength / 8 + 5); + + // first byte is width; + irisFeaturePtr[0] = (uchar)width; + irisFeaturePtr[1] = (uchar)(width >> 8); + + // second byte is height; + irisFeaturePtr[2] = (uchar)height; + + // third byte is n_codes + irisFeaturePtr[3] = (uchar)n_codes; + + // fourth byte is n_mask(1) + irisFeaturePtr[4] = (uchar)1; + for (int i = 0; i < irisDataLength; i++) { + irisFeaturePtr[5 + i / 8] += irisData[i] << (7 - (i % 8)); + } + + QByteArray feature; + for (int i = 0; i < irisDataLength / 8 + 5; i++) { + feature.append((char) irisFeaturePtr[i]); + } + + delete[] irisData; + delete[] irisFeaturePtr; + return feature; } float CasicIrisRec::matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2) @@ -283,6 +374,67 @@ } +float CasicIrisRec::matchFeatureCode(uchar *feature1, uchar *feature2) +{ + int width = feature1[0] | feature1[1] << 8; // 32 + int height = feature1[2]; // 8 + int nCode = feature1[3]; // 6 +// int nMask = feature1[4]; + + uchar ** irisData1 = reduceIrisCode(feature1); + uchar ** irisMask1 = reduceIrisMask(feature1); + uchar ** irisData2 = reduceIrisCode(feature2); + uchar ** irisMask2 = reduceIrisMask(feature2); + + int shift = 10; + float score = 1.0; + + int minstep = 0 - shift; + int maxstep = shift; + + for (int s = minstep; s <= maxstep; s++) { + int count = 0; + float mean = 0.0; + for (int n = 0; n < nCode; n++) { + for (auto pos : mvApplicationPoints) { + int row = pos.first / mvApplicationPoints[0].first - 1; + int col = (pos.second + s + width) % width; + + if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { + + uchar tmp1 = irisData1[row + height * n][col]; + uchar tmp2 = irisData2[row + height * n][pos.second]; + mean += tmp1 ^ tmp2; + count += 1; + } + } + } + + //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; + mean = mean / count; + score = mean < score ? mean : score; + + } + +// std::cout << "feature score: " << score << std::endl; + + +// for (int i = 0; i < height * nCode; i++) { +// delete irisData1[i]; +// delete irisData2[i]; +// } +// delete irisData1; +// delete irisData2; + +// for (int i = 0; i < height; i++) { +// delete irisMask1[i]; +// delete irisMask2[i]; +// } +// delete irisMask1; +// delete irisMask2; + return score; +} + cv::Mat CasicIrisRec::addBorders(cv::Mat pSrc, int width) { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); @@ -298,4 +450,39 @@ return result; } +uchar ** CasicIrisRec::reduceIrisCode(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2] * feature[3]; + + uchar ** reduceCode = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + reduceCode[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = i * width + j; + reduceCode[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return reduceCode; +} + +uchar ** CasicIrisRec::reduceIrisMask(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2]; // 8 + int nCode = feature[3]; // 6 + + uchar ** irisMask = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + irisMask[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = width * height * nCode + i * width + j; + irisMask[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return irisMask; +} + } diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index 1558461..c528381 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -87,9 +87,6 @@ this->cascade->load(cascadeName); } - QElapsedTimer timer; - timer.start(); - std::vector rect; cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); @@ -111,8 +108,8 @@ // .arg(timer.elapsed()).arg(rect.size()) // .arg(rect.at(0).x).arg(rect.at(0).y) // .arg(rect.at(0).width).arg(rect.at(0).height).toStdString()); - qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]") - .arg(timer.elapsed()).arg(rect.size()) + qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]") + .arg(rect.size()) .arg(rect.at(0).x).arg(rect.at(0).y) .arg(rect.at(0).width).arg(rect.at(0).height); @@ -141,20 +138,18 @@ } // 裁剪眼部图像 - cv::Mat halfSize = irisInfo.matData.clone(); - halfSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, + cv::Mat cutSize = irisInfo.matData.clone(); + cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5, SettingConfig::getInstance().IRIS_WIDTH * cutRatio, SettingConfig::getInstance().IRIS_HEIGHT * cutRatio)); - cv::resize(halfSize, halfSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); - cv::flip(halfSize, halfSize, 1); // 左右翻转 + // 裁剪后放大到 640 * 480 + cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); + cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; -// irisInfo.eyeRect = rect.at(0); - - irisInfo.matData = halfSize; -// irisInfo.data = ImageUtil::MatImageToQImage(halfSize); + irisInfo.matData = cutSize; return irisInfo; } @@ -229,9 +224,18 @@ return irisInfo; } +QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo) +{ + QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm); + return irisFeatureCode; +} + float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo) { -// cv::imshow("info", irisInfo.irisCode); -// cv::waitKey(0); return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm); } + +float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other) +{ + return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data())); +} diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index cbee8fe..26fbedc 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -27,7 +27,9 @@ CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); + QByteArray extractFeature(CasicIrisInfo irisInfo); float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo); + float calculatePairPoints(QByteArray feature, QByteArray other); void setCascadeFile(QString filename); void setMinEyeSize(int minEyeSize); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index c8ffe3e..ad456b4 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -177,6 +177,8 @@ // Get the coordinates file >> i; file >> j; + mvApplicationPoints.push_back(QPair(i, j)); + // Set pixel to "on" if (i < 0 || i > applicationPoints.rows - 1 || j < 0 || j > applicationPoints.cols- 1) { @@ -237,7 +239,96 @@ roi.copyTo(dst); //cv::copyTo(img2, dst, NULL); } - return encodeImage; + cv::Mat image8UC1; + encodeImage.convertTo(image8UC1, CV_8UC1); + return image8UC1; +} + +QByteArray CasicIrisRec::extractFeature(cv::Mat irisCode, cv::Mat maskNorm) +{ + // count points width and height + cv::Mat pointTemp(applicationPoints); + cv::Mat rowTemp; + + std::vector pointRows; + for (int i = 0; i < applicationPoints.rows; i++) { + rowTemp = pointTemp(cv::Rect(0, i, applicationPoints.cols, 1)); + if (cv::sum(rowTemp)[0] > 0) { + pointRows.push_back(i); + } + } + + int width = irisCode.cols; + int height = pointRows.size(); + rowTemp.release(); + pointTemp.release(); + + int n_codes = irisCode.rows / applicationPoints.rows; + + int irisDataLength = (n_codes + 1) * width * height; + uchar * irisData = new uchar[irisDataLength]; + int irisDataIndex = 0; + + uchar* codePixel = new uchar; + + // save iris code 512 * 8 * 6 + for (int n = 0; n < n_codes; n++) { // 6 + for (auto i : pointRows) { // 8 + i = n * maskNorm.rows + i; + for (int j = 0; j < irisCode.cols; j++) { // 512 + codePixel = (uchar*)(irisCode.data + i * irisCode.step + j); + if (*codePixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *codePixel; + } + } + } + } + + // save iris mask 512 * 8 * 1 + uchar * maskPixel; + for (auto i : pointRows) { // 8 + for (int j = 0; j < irisCode.cols; j++) { // 512 + maskPixel = (uchar*)(maskNorm.data + i * maskNorm.step + j); + if (*maskPixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *maskPixel; + } + } + } + + + uchar * irisFeaturePtr = new uchar[irisDataLength / 8 + 5]; + memset(irisFeaturePtr, 0, irisDataLength / 8 + 5); + + // first byte is width; + irisFeaturePtr[0] = (uchar)width; + irisFeaturePtr[1] = (uchar)(width >> 8); + + // second byte is height; + irisFeaturePtr[2] = (uchar)height; + + // third byte is n_codes + irisFeaturePtr[3] = (uchar)n_codes; + + // fourth byte is n_mask(1) + irisFeaturePtr[4] = (uchar)1; + for (int i = 0; i < irisDataLength; i++) { + irisFeaturePtr[5 + i / 8] += irisData[i] << (7 - (i % 8)); + } + + QByteArray feature; + for (int i = 0; i < irisDataLength / 8 + 5; i++) { + feature.append((char) irisFeaturePtr[i]); + } + + delete[] irisData; + delete[] irisFeaturePtr; + return feature; } float CasicIrisRec::matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2) @@ -283,6 +374,67 @@ } +float CasicIrisRec::matchFeatureCode(uchar *feature1, uchar *feature2) +{ + int width = feature1[0] | feature1[1] << 8; // 32 + int height = feature1[2]; // 8 + int nCode = feature1[3]; // 6 +// int nMask = feature1[4]; + + uchar ** irisData1 = reduceIrisCode(feature1); + uchar ** irisMask1 = reduceIrisMask(feature1); + uchar ** irisData2 = reduceIrisCode(feature2); + uchar ** irisMask2 = reduceIrisMask(feature2); + + int shift = 10; + float score = 1.0; + + int minstep = 0 - shift; + int maxstep = shift; + + for (int s = minstep; s <= maxstep; s++) { + int count = 0; + float mean = 0.0; + for (int n = 0; n < nCode; n++) { + for (auto pos : mvApplicationPoints) { + int row = pos.first / mvApplicationPoints[0].first - 1; + int col = (pos.second + s + width) % width; + + if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { + + uchar tmp1 = irisData1[row + height * n][col]; + uchar tmp2 = irisData2[row + height * n][pos.second]; + mean += tmp1 ^ tmp2; + count += 1; + } + } + } + + //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; + mean = mean / count; + score = mean < score ? mean : score; + + } + +// std::cout << "feature score: " << score << std::endl; + + +// for (int i = 0; i < height * nCode; i++) { +// delete irisData1[i]; +// delete irisData2[i]; +// } +// delete irisData1; +// delete irisData2; + +// for (int i = 0; i < height; i++) { +// delete irisMask1[i]; +// delete irisMask2[i]; +// } +// delete irisMask1; +// delete irisMask2; + return score; +} + cv::Mat CasicIrisRec::addBorders(cv::Mat pSrc, int width) { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); @@ -298,4 +450,39 @@ return result; } +uchar ** CasicIrisRec::reduceIrisCode(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2] * feature[3]; + + uchar ** reduceCode = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + reduceCode[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = i * width + j; + reduceCode[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return reduceCode; +} + +uchar ** CasicIrisRec::reduceIrisMask(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2]; // 8 + int nCode = feature[3]; // 6 + + uchar ** irisMask = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + irisMask[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = width * height * nCode + i * width + j; + irisMask[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return irisMask; +} + } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index f6ca8ac..2d9616e 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -5,6 +5,8 @@ #define NORM_HEIGHT 64 #define M_PI 3.1415926535897323846 +#include +#include #include namespace iristrt @@ -15,28 +17,28 @@ public: CasicIrisRec(); - CasicIrisRec(const char * gaborFilterFileName,const char * applicationPointsFileName); - ~CasicIrisRec(); cv::Mat normalize(cv::Mat image, int iris_x, int iris_y, int iris_r,int pupil_x, int pupil_y, int pupil_r); - cv::Mat encodeToImage(cv::Mat normalizedImage); + QByteArray extractFeature(cv::Mat irisCode, cv::Mat maskNorm); float matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2); + float matchFeatureCode(uchar * feature1, uchar * feature2); private: std::vector gaborFilters; - cv::Mat applicationPoints; + std::vector> mvApplicationPoints; std::vector loadGaborFilters(const char * gaborFilterFileName); - cv::Mat loadApplicationPoints(const char * applicationPointsFileName); cv::Mat addBorders(cv::Mat pSrc, int width); + uchar ** reduceIrisCode(uchar * feature); + uchar ** reduceIrisMask(uchar * feature); }; // end of class CasicIrisRec diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index 1558461..c528381 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -87,9 +87,6 @@ this->cascade->load(cascadeName); } - QElapsedTimer timer; - timer.start(); - std::vector rect; cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); @@ -111,8 +108,8 @@ // .arg(timer.elapsed()).arg(rect.size()) // .arg(rect.at(0).x).arg(rect.at(0).y) // .arg(rect.at(0).width).arg(rect.at(0).height).toStdString()); - qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]") - .arg(timer.elapsed()).arg(rect.size()) + qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]") + .arg(rect.size()) .arg(rect.at(0).x).arg(rect.at(0).y) .arg(rect.at(0).width).arg(rect.at(0).height); @@ -141,20 +138,18 @@ } // 裁剪眼部图像 - cv::Mat halfSize = irisInfo.matData.clone(); - halfSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, + cv::Mat cutSize = irisInfo.matData.clone(); + cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5, SettingConfig::getInstance().IRIS_WIDTH * cutRatio, SettingConfig::getInstance().IRIS_HEIGHT * cutRatio)); - cv::resize(halfSize, halfSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); - cv::flip(halfSize, halfSize, 1); // 左右翻转 + // 裁剪后放大到 640 * 480 + cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); + cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; -// irisInfo.eyeRect = rect.at(0); - - irisInfo.matData = halfSize; -// irisInfo.data = ImageUtil::MatImageToQImage(halfSize); + irisInfo.matData = cutSize; return irisInfo; } @@ -229,9 +224,18 @@ return irisInfo; } +QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo) +{ + QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm); + return irisFeatureCode; +} + float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo) { -// cv::imshow("info", irisInfo.irisCode); -// cv::waitKey(0); return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm); } + +float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other) +{ + return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data())); +} diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index cbee8fe..26fbedc 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -27,7 +27,9 @@ CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); + QByteArray extractFeature(CasicIrisInfo irisInfo); float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo); + float calculatePairPoints(QByteArray feature, QByteArray other); void setCascadeFile(QString filename); void setMinEyeSize(int minEyeSize); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index c8ffe3e..ad456b4 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -177,6 +177,8 @@ // Get the coordinates file >> i; file >> j; + mvApplicationPoints.push_back(QPair(i, j)); + // Set pixel to "on" if (i < 0 || i > applicationPoints.rows - 1 || j < 0 || j > applicationPoints.cols- 1) { @@ -237,7 +239,96 @@ roi.copyTo(dst); //cv::copyTo(img2, dst, NULL); } - return encodeImage; + cv::Mat image8UC1; + encodeImage.convertTo(image8UC1, CV_8UC1); + return image8UC1; +} + +QByteArray CasicIrisRec::extractFeature(cv::Mat irisCode, cv::Mat maskNorm) +{ + // count points width and height + cv::Mat pointTemp(applicationPoints); + cv::Mat rowTemp; + + std::vector pointRows; + for (int i = 0; i < applicationPoints.rows; i++) { + rowTemp = pointTemp(cv::Rect(0, i, applicationPoints.cols, 1)); + if (cv::sum(rowTemp)[0] > 0) { + pointRows.push_back(i); + } + } + + int width = irisCode.cols; + int height = pointRows.size(); + rowTemp.release(); + pointTemp.release(); + + int n_codes = irisCode.rows / applicationPoints.rows; + + int irisDataLength = (n_codes + 1) * width * height; + uchar * irisData = new uchar[irisDataLength]; + int irisDataIndex = 0; + + uchar* codePixel = new uchar; + + // save iris code 512 * 8 * 6 + for (int n = 0; n < n_codes; n++) { // 6 + for (auto i : pointRows) { // 8 + i = n * maskNorm.rows + i; + for (int j = 0; j < irisCode.cols; j++) { // 512 + codePixel = (uchar*)(irisCode.data + i * irisCode.step + j); + if (*codePixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *codePixel; + } + } + } + } + + // save iris mask 512 * 8 * 1 + uchar * maskPixel; + for (auto i : pointRows) { // 8 + for (int j = 0; j < irisCode.cols; j++) { // 512 + maskPixel = (uchar*)(maskNorm.data + i * maskNorm.step + j); + if (*maskPixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *maskPixel; + } + } + } + + + uchar * irisFeaturePtr = new uchar[irisDataLength / 8 + 5]; + memset(irisFeaturePtr, 0, irisDataLength / 8 + 5); + + // first byte is width; + irisFeaturePtr[0] = (uchar)width; + irisFeaturePtr[1] = (uchar)(width >> 8); + + // second byte is height; + irisFeaturePtr[2] = (uchar)height; + + // third byte is n_codes + irisFeaturePtr[3] = (uchar)n_codes; + + // fourth byte is n_mask(1) + irisFeaturePtr[4] = (uchar)1; + for (int i = 0; i < irisDataLength; i++) { + irisFeaturePtr[5 + i / 8] += irisData[i] << (7 - (i % 8)); + } + + QByteArray feature; + for (int i = 0; i < irisDataLength / 8 + 5; i++) { + feature.append((char) irisFeaturePtr[i]); + } + + delete[] irisData; + delete[] irisFeaturePtr; + return feature; } float CasicIrisRec::matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2) @@ -283,6 +374,67 @@ } +float CasicIrisRec::matchFeatureCode(uchar *feature1, uchar *feature2) +{ + int width = feature1[0] | feature1[1] << 8; // 32 + int height = feature1[2]; // 8 + int nCode = feature1[3]; // 6 +// int nMask = feature1[4]; + + uchar ** irisData1 = reduceIrisCode(feature1); + uchar ** irisMask1 = reduceIrisMask(feature1); + uchar ** irisData2 = reduceIrisCode(feature2); + uchar ** irisMask2 = reduceIrisMask(feature2); + + int shift = 10; + float score = 1.0; + + int minstep = 0 - shift; + int maxstep = shift; + + for (int s = minstep; s <= maxstep; s++) { + int count = 0; + float mean = 0.0; + for (int n = 0; n < nCode; n++) { + for (auto pos : mvApplicationPoints) { + int row = pos.first / mvApplicationPoints[0].first - 1; + int col = (pos.second + s + width) % width; + + if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { + + uchar tmp1 = irisData1[row + height * n][col]; + uchar tmp2 = irisData2[row + height * n][pos.second]; + mean += tmp1 ^ tmp2; + count += 1; + } + } + } + + //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; + mean = mean / count; + score = mean < score ? mean : score; + + } + +// std::cout << "feature score: " << score << std::endl; + + +// for (int i = 0; i < height * nCode; i++) { +// delete irisData1[i]; +// delete irisData2[i]; +// } +// delete irisData1; +// delete irisData2; + +// for (int i = 0; i < height; i++) { +// delete irisMask1[i]; +// delete irisMask2[i]; +// } +// delete irisMask1; +// delete irisMask2; + return score; +} + cv::Mat CasicIrisRec::addBorders(cv::Mat pSrc, int width) { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); @@ -298,4 +450,39 @@ return result; } +uchar ** CasicIrisRec::reduceIrisCode(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2] * feature[3]; + + uchar ** reduceCode = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + reduceCode[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = i * width + j; + reduceCode[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return reduceCode; +} + +uchar ** CasicIrisRec::reduceIrisMask(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2]; // 8 + int nCode = feature[3]; // 6 + + uchar ** irisMask = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + irisMask[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = width * height * nCode + i * width + j; + irisMask[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return irisMask; +} + } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index f6ca8ac..2d9616e 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -5,6 +5,8 @@ #define NORM_HEIGHT 64 #define M_PI 3.1415926535897323846 +#include +#include #include namespace iristrt @@ -15,28 +17,28 @@ public: CasicIrisRec(); - CasicIrisRec(const char * gaborFilterFileName,const char * applicationPointsFileName); - ~CasicIrisRec(); cv::Mat normalize(cv::Mat image, int iris_x, int iris_y, int iris_r,int pupil_x, int pupil_y, int pupil_r); - cv::Mat encodeToImage(cv::Mat normalizedImage); + QByteArray extractFeature(cv::Mat irisCode, cv::Mat maskNorm); float matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2); + float matchFeatureCode(uchar * feature1, uchar * feature2); private: std::vector gaborFilters; - cv::Mat applicationPoints; + std::vector> mvApplicationPoints; std::vector loadGaborFilters(const char * gaborFilterFileName); - cv::Mat loadApplicationPoints(const char * applicationPointsFileName); cv::Mat addBorders(cv::Mat pSrc, int width); + uchar ** reduceIrisCode(uchar * feature); + uchar ** reduceIrisMask(uchar * feature); }; // end of class CasicIrisRec diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 37a0ed6..63eda4d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,3 +1,7 @@ +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + #include "IrisDataDao.h" IrisDataDao::IrisDataDao(QObject *parent) : BaseDao(parent) @@ -37,7 +41,7 @@ result.append(item); } -// LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } @@ -104,7 +108,7 @@ result.insert("right_iris_code3", query.value("right_iris_code3")); } -// LOG_DEBUG(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); + LOG_TRACE(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); return result; } @@ -114,7 +118,12 @@ // 新建查询 QSqlQuery query(ConnectionManager::getInstance()->getConnection()); - qulonglong id = ConnectionManager::getInstance()->generateId(); + qulonglong id; + if (object.contains("id") == true) { + id = object.value("id").toULongLong(); + } else { + id = ConnectionManager::getInstance()->generateId(); + } // INSERT语句 QString sql = QString("INSERT INTO IRIS_DATA (ID, PERSON_ID, ID_CARD_NO, LEFT_IRIS_CODE1, RIGHT_IRIS_CODE1) VALUES (:id, :personId, :idCardNo, :left1, :right1)"); @@ -132,7 +141,7 @@ // 执行插入 bool success = query.exec(); -// LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); + LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); // 结束事务 ConnectionManager::getInstance()->getConnection().commit(); diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index 1558461..c528381 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -87,9 +87,6 @@ this->cascade->load(cascadeName); } - QElapsedTimer timer; - timer.start(); - std::vector rect; cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); @@ -111,8 +108,8 @@ // .arg(timer.elapsed()).arg(rect.size()) // .arg(rect.at(0).x).arg(rect.at(0).y) // .arg(rect.at(0).width).arg(rect.at(0).height).toStdString()); - qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]") - .arg(timer.elapsed()).arg(rect.size()) + qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]") + .arg(rect.size()) .arg(rect.at(0).x).arg(rect.at(0).y) .arg(rect.at(0).width).arg(rect.at(0).height); @@ -141,20 +138,18 @@ } // 裁剪眼部图像 - cv::Mat halfSize = irisInfo.matData.clone(); - halfSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, + cv::Mat cutSize = irisInfo.matData.clone(); + cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5, SettingConfig::getInstance().IRIS_WIDTH * cutRatio, SettingConfig::getInstance().IRIS_HEIGHT * cutRatio)); - cv::resize(halfSize, halfSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); - cv::flip(halfSize, halfSize, 1); // 左右翻转 + // 裁剪后放大到 640 * 480 + cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); + cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; -// irisInfo.eyeRect = rect.at(0); - - irisInfo.matData = halfSize; -// irisInfo.data = ImageUtil::MatImageToQImage(halfSize); + irisInfo.matData = cutSize; return irisInfo; } @@ -229,9 +224,18 @@ return irisInfo; } +QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo) +{ + QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm); + return irisFeatureCode; +} + float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo) { -// cv::imshow("info", irisInfo.irisCode); -// cv::waitKey(0); return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm); } + +float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other) +{ + return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data())); +} diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index cbee8fe..26fbedc 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -27,7 +27,9 @@ CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); + QByteArray extractFeature(CasicIrisInfo irisInfo); float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo); + float calculatePairPoints(QByteArray feature, QByteArray other); void setCascadeFile(QString filename); void setMinEyeSize(int minEyeSize); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index c8ffe3e..ad456b4 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -177,6 +177,8 @@ // Get the coordinates file >> i; file >> j; + mvApplicationPoints.push_back(QPair(i, j)); + // Set pixel to "on" if (i < 0 || i > applicationPoints.rows - 1 || j < 0 || j > applicationPoints.cols- 1) { @@ -237,7 +239,96 @@ roi.copyTo(dst); //cv::copyTo(img2, dst, NULL); } - return encodeImage; + cv::Mat image8UC1; + encodeImage.convertTo(image8UC1, CV_8UC1); + return image8UC1; +} + +QByteArray CasicIrisRec::extractFeature(cv::Mat irisCode, cv::Mat maskNorm) +{ + // count points width and height + cv::Mat pointTemp(applicationPoints); + cv::Mat rowTemp; + + std::vector pointRows; + for (int i = 0; i < applicationPoints.rows; i++) { + rowTemp = pointTemp(cv::Rect(0, i, applicationPoints.cols, 1)); + if (cv::sum(rowTemp)[0] > 0) { + pointRows.push_back(i); + } + } + + int width = irisCode.cols; + int height = pointRows.size(); + rowTemp.release(); + pointTemp.release(); + + int n_codes = irisCode.rows / applicationPoints.rows; + + int irisDataLength = (n_codes + 1) * width * height; + uchar * irisData = new uchar[irisDataLength]; + int irisDataIndex = 0; + + uchar* codePixel = new uchar; + + // save iris code 512 * 8 * 6 + for (int n = 0; n < n_codes; n++) { // 6 + for (auto i : pointRows) { // 8 + i = n * maskNorm.rows + i; + for (int j = 0; j < irisCode.cols; j++) { // 512 + codePixel = (uchar*)(irisCode.data + i * irisCode.step + j); + if (*codePixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *codePixel; + } + } + } + } + + // save iris mask 512 * 8 * 1 + uchar * maskPixel; + for (auto i : pointRows) { // 8 + for (int j = 0; j < irisCode.cols; j++) { // 512 + maskPixel = (uchar*)(maskNorm.data + i * maskNorm.step + j); + if (*maskPixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *maskPixel; + } + } + } + + + uchar * irisFeaturePtr = new uchar[irisDataLength / 8 + 5]; + memset(irisFeaturePtr, 0, irisDataLength / 8 + 5); + + // first byte is width; + irisFeaturePtr[0] = (uchar)width; + irisFeaturePtr[1] = (uchar)(width >> 8); + + // second byte is height; + irisFeaturePtr[2] = (uchar)height; + + // third byte is n_codes + irisFeaturePtr[3] = (uchar)n_codes; + + // fourth byte is n_mask(1) + irisFeaturePtr[4] = (uchar)1; + for (int i = 0; i < irisDataLength; i++) { + irisFeaturePtr[5 + i / 8] += irisData[i] << (7 - (i % 8)); + } + + QByteArray feature; + for (int i = 0; i < irisDataLength / 8 + 5; i++) { + feature.append((char) irisFeaturePtr[i]); + } + + delete[] irisData; + delete[] irisFeaturePtr; + return feature; } float CasicIrisRec::matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2) @@ -283,6 +374,67 @@ } +float CasicIrisRec::matchFeatureCode(uchar *feature1, uchar *feature2) +{ + int width = feature1[0] | feature1[1] << 8; // 32 + int height = feature1[2]; // 8 + int nCode = feature1[3]; // 6 +// int nMask = feature1[4]; + + uchar ** irisData1 = reduceIrisCode(feature1); + uchar ** irisMask1 = reduceIrisMask(feature1); + uchar ** irisData2 = reduceIrisCode(feature2); + uchar ** irisMask2 = reduceIrisMask(feature2); + + int shift = 10; + float score = 1.0; + + int minstep = 0 - shift; + int maxstep = shift; + + for (int s = minstep; s <= maxstep; s++) { + int count = 0; + float mean = 0.0; + for (int n = 0; n < nCode; n++) { + for (auto pos : mvApplicationPoints) { + int row = pos.first / mvApplicationPoints[0].first - 1; + int col = (pos.second + s + width) % width; + + if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { + + uchar tmp1 = irisData1[row + height * n][col]; + uchar tmp2 = irisData2[row + height * n][pos.second]; + mean += tmp1 ^ tmp2; + count += 1; + } + } + } + + //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; + mean = mean / count; + score = mean < score ? mean : score; + + } + +// std::cout << "feature score: " << score << std::endl; + + +// for (int i = 0; i < height * nCode; i++) { +// delete irisData1[i]; +// delete irisData2[i]; +// } +// delete irisData1; +// delete irisData2; + +// for (int i = 0; i < height; i++) { +// delete irisMask1[i]; +// delete irisMask2[i]; +// } +// delete irisMask1; +// delete irisMask2; + return score; +} + cv::Mat CasicIrisRec::addBorders(cv::Mat pSrc, int width) { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); @@ -298,4 +450,39 @@ return result; } +uchar ** CasicIrisRec::reduceIrisCode(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2] * feature[3]; + + uchar ** reduceCode = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + reduceCode[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = i * width + j; + reduceCode[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return reduceCode; +} + +uchar ** CasicIrisRec::reduceIrisMask(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2]; // 8 + int nCode = feature[3]; // 6 + + uchar ** irisMask = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + irisMask[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = width * height * nCode + i * width + j; + irisMask[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return irisMask; +} + } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index f6ca8ac..2d9616e 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -5,6 +5,8 @@ #define NORM_HEIGHT 64 #define M_PI 3.1415926535897323846 +#include +#include #include namespace iristrt @@ -15,28 +17,28 @@ public: CasicIrisRec(); - CasicIrisRec(const char * gaborFilterFileName,const char * applicationPointsFileName); - ~CasicIrisRec(); cv::Mat normalize(cv::Mat image, int iris_x, int iris_y, int iris_r,int pupil_x, int pupil_y, int pupil_r); - cv::Mat encodeToImage(cv::Mat normalizedImage); + QByteArray extractFeature(cv::Mat irisCode, cv::Mat maskNorm); float matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2); + float matchFeatureCode(uchar * feature1, uchar * feature2); private: std::vector gaborFilters; - cv::Mat applicationPoints; + std::vector> mvApplicationPoints; std::vector loadGaborFilters(const char * gaborFilterFileName); - cv::Mat loadApplicationPoints(const char * applicationPointsFileName); cv::Mat addBorders(cv::Mat pSrc, int width); + uchar ** reduceIrisCode(uchar * feature); + uchar ** reduceIrisMask(uchar * feature); }; // end of class CasicIrisRec diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 37a0ed6..63eda4d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,3 +1,7 @@ +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + #include "IrisDataDao.h" IrisDataDao::IrisDataDao(QObject *parent) : BaseDao(parent) @@ -37,7 +41,7 @@ result.append(item); } -// LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } @@ -104,7 +108,7 @@ result.insert("right_iris_code3", query.value("right_iris_code3")); } -// LOG_DEBUG(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); + LOG_TRACE(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); return result; } @@ -114,7 +118,12 @@ // 新建查询 QSqlQuery query(ConnectionManager::getInstance()->getConnection()); - qulonglong id = ConnectionManager::getInstance()->generateId(); + qulonglong id; + if (object.contains("id") == true) { + id = object.value("id").toULongLong(); + } else { + id = ConnectionManager::getInstance()->generateId(); + } // INSERT语句 QString sql = QString("INSERT INTO IRIS_DATA (ID, PERSON_ID, ID_CARD_NO, LEFT_IRIS_CODE1, RIGHT_IRIS_CODE1) VALUES (:id, :personId, :idCardNo, :left1, :right1)"); @@ -132,7 +141,7 @@ // 执行插入 bool success = query.exec(); -// LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); + LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); // 结束事务 ConnectionManager::getInstance()->getConnection().commit(); diff --git a/dao/RecognitionRecordsDao.cpp b/dao/RecognitionRecordsDao.cpp index 40db453..d795039 100644 --- a/dao/RecognitionRecordsDao.cpp +++ b/dao/RecognitionRecordsDao.cpp @@ -1,4 +1,4 @@ -#include "RecognitionRecordsDao.h" +#include "RecognitionRecordsDao.h" RecognitionRecordsDao::RecognitionRecordsDao(QObject *parent) : BaseDao(parent) { @@ -58,10 +58,8 @@ query.bindValue(":doorCode", object.value("door_code").toString()); query.bindValue(":inoutType", object.value("inout_type").toString()); -// LOG_DEBUG(sql.toStdString()); - // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES (:id, :logInfo)"); + QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES (:id, :logInfo)"); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index 1558461..c528381 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -87,9 +87,6 @@ this->cascade->load(cascadeName); } - QElapsedTimer timer; - timer.start(); - std::vector rect; cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); @@ -111,8 +108,8 @@ // .arg(timer.elapsed()).arg(rect.size()) // .arg(rect.at(0).x).arg(rect.at(0).y) // .arg(rect.at(0).width).arg(rect.at(0).height).toStdString()); - qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]") - .arg(timer.elapsed()).arg(rect.size()) + qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]") + .arg(rect.size()) .arg(rect.at(0).x).arg(rect.at(0).y) .arg(rect.at(0).width).arg(rect.at(0).height); @@ -141,20 +138,18 @@ } // 裁剪眼部图像 - cv::Mat halfSize = irisInfo.matData.clone(); - halfSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, + cv::Mat cutSize = irisInfo.matData.clone(); + cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5, SettingConfig::getInstance().IRIS_WIDTH * cutRatio, SettingConfig::getInstance().IRIS_HEIGHT * cutRatio)); - cv::resize(halfSize, halfSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); - cv::flip(halfSize, halfSize, 1); // 左右翻转 + // 裁剪后放大到 640 * 480 + cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); + cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; -// irisInfo.eyeRect = rect.at(0); - - irisInfo.matData = halfSize; -// irisInfo.data = ImageUtil::MatImageToQImage(halfSize); + irisInfo.matData = cutSize; return irisInfo; } @@ -229,9 +224,18 @@ return irisInfo; } +QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo) +{ + QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm); + return irisFeatureCode; +} + float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo) { -// cv::imshow("info", irisInfo.irisCode); -// cv::waitKey(0); return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm); } + +float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other) +{ + return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data())); +} diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index cbee8fe..26fbedc 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -27,7 +27,9 @@ CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); + QByteArray extractFeature(CasicIrisInfo irisInfo); float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo); + float calculatePairPoints(QByteArray feature, QByteArray other); void setCascadeFile(QString filename); void setMinEyeSize(int minEyeSize); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index c8ffe3e..ad456b4 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -177,6 +177,8 @@ // Get the coordinates file >> i; file >> j; + mvApplicationPoints.push_back(QPair(i, j)); + // Set pixel to "on" if (i < 0 || i > applicationPoints.rows - 1 || j < 0 || j > applicationPoints.cols- 1) { @@ -237,7 +239,96 @@ roi.copyTo(dst); //cv::copyTo(img2, dst, NULL); } - return encodeImage; + cv::Mat image8UC1; + encodeImage.convertTo(image8UC1, CV_8UC1); + return image8UC1; +} + +QByteArray CasicIrisRec::extractFeature(cv::Mat irisCode, cv::Mat maskNorm) +{ + // count points width and height + cv::Mat pointTemp(applicationPoints); + cv::Mat rowTemp; + + std::vector pointRows; + for (int i = 0; i < applicationPoints.rows; i++) { + rowTemp = pointTemp(cv::Rect(0, i, applicationPoints.cols, 1)); + if (cv::sum(rowTemp)[0] > 0) { + pointRows.push_back(i); + } + } + + int width = irisCode.cols; + int height = pointRows.size(); + rowTemp.release(); + pointTemp.release(); + + int n_codes = irisCode.rows / applicationPoints.rows; + + int irisDataLength = (n_codes + 1) * width * height; + uchar * irisData = new uchar[irisDataLength]; + int irisDataIndex = 0; + + uchar* codePixel = new uchar; + + // save iris code 512 * 8 * 6 + for (int n = 0; n < n_codes; n++) { // 6 + for (auto i : pointRows) { // 8 + i = n * maskNorm.rows + i; + for (int j = 0; j < irisCode.cols; j++) { // 512 + codePixel = (uchar*)(irisCode.data + i * irisCode.step + j); + if (*codePixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *codePixel; + } + } + } + } + + // save iris mask 512 * 8 * 1 + uchar * maskPixel; + for (auto i : pointRows) { // 8 + for (int j = 0; j < irisCode.cols; j++) { // 512 + maskPixel = (uchar*)(maskNorm.data + i * maskNorm.step + j); + if (*maskPixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *maskPixel; + } + } + } + + + uchar * irisFeaturePtr = new uchar[irisDataLength / 8 + 5]; + memset(irisFeaturePtr, 0, irisDataLength / 8 + 5); + + // first byte is width; + irisFeaturePtr[0] = (uchar)width; + irisFeaturePtr[1] = (uchar)(width >> 8); + + // second byte is height; + irisFeaturePtr[2] = (uchar)height; + + // third byte is n_codes + irisFeaturePtr[3] = (uchar)n_codes; + + // fourth byte is n_mask(1) + irisFeaturePtr[4] = (uchar)1; + for (int i = 0; i < irisDataLength; i++) { + irisFeaturePtr[5 + i / 8] += irisData[i] << (7 - (i % 8)); + } + + QByteArray feature; + for (int i = 0; i < irisDataLength / 8 + 5; i++) { + feature.append((char) irisFeaturePtr[i]); + } + + delete[] irisData; + delete[] irisFeaturePtr; + return feature; } float CasicIrisRec::matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2) @@ -283,6 +374,67 @@ } +float CasicIrisRec::matchFeatureCode(uchar *feature1, uchar *feature2) +{ + int width = feature1[0] | feature1[1] << 8; // 32 + int height = feature1[2]; // 8 + int nCode = feature1[3]; // 6 +// int nMask = feature1[4]; + + uchar ** irisData1 = reduceIrisCode(feature1); + uchar ** irisMask1 = reduceIrisMask(feature1); + uchar ** irisData2 = reduceIrisCode(feature2); + uchar ** irisMask2 = reduceIrisMask(feature2); + + int shift = 10; + float score = 1.0; + + int minstep = 0 - shift; + int maxstep = shift; + + for (int s = minstep; s <= maxstep; s++) { + int count = 0; + float mean = 0.0; + for (int n = 0; n < nCode; n++) { + for (auto pos : mvApplicationPoints) { + int row = pos.first / mvApplicationPoints[0].first - 1; + int col = (pos.second + s + width) % width; + + if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { + + uchar tmp1 = irisData1[row + height * n][col]; + uchar tmp2 = irisData2[row + height * n][pos.second]; + mean += tmp1 ^ tmp2; + count += 1; + } + } + } + + //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; + mean = mean / count; + score = mean < score ? mean : score; + + } + +// std::cout << "feature score: " << score << std::endl; + + +// for (int i = 0; i < height * nCode; i++) { +// delete irisData1[i]; +// delete irisData2[i]; +// } +// delete irisData1; +// delete irisData2; + +// for (int i = 0; i < height; i++) { +// delete irisMask1[i]; +// delete irisMask2[i]; +// } +// delete irisMask1; +// delete irisMask2; + return score; +} + cv::Mat CasicIrisRec::addBorders(cv::Mat pSrc, int width) { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); @@ -298,4 +450,39 @@ return result; } +uchar ** CasicIrisRec::reduceIrisCode(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2] * feature[3]; + + uchar ** reduceCode = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + reduceCode[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = i * width + j; + reduceCode[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return reduceCode; +} + +uchar ** CasicIrisRec::reduceIrisMask(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2]; // 8 + int nCode = feature[3]; // 6 + + uchar ** irisMask = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + irisMask[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = width * height * nCode + i * width + j; + irisMask[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return irisMask; +} + } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index f6ca8ac..2d9616e 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -5,6 +5,8 @@ #define NORM_HEIGHT 64 #define M_PI 3.1415926535897323846 +#include +#include #include namespace iristrt @@ -15,28 +17,28 @@ public: CasicIrisRec(); - CasicIrisRec(const char * gaborFilterFileName,const char * applicationPointsFileName); - ~CasicIrisRec(); cv::Mat normalize(cv::Mat image, int iris_x, int iris_y, int iris_r,int pupil_x, int pupil_y, int pupil_r); - cv::Mat encodeToImage(cv::Mat normalizedImage); + QByteArray extractFeature(cv::Mat irisCode, cv::Mat maskNorm); float matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2); + float matchFeatureCode(uchar * feature1, uchar * feature2); private: std::vector gaborFilters; - cv::Mat applicationPoints; + std::vector> mvApplicationPoints; std::vector loadGaborFilters(const char * gaborFilterFileName); - cv::Mat loadApplicationPoints(const char * applicationPointsFileName); cv::Mat addBorders(cv::Mat pSrc, int width); + uchar ** reduceIrisCode(uchar * feature); + uchar ** reduceIrisMask(uchar * feature); }; // end of class CasicIrisRec diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 37a0ed6..63eda4d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,3 +1,7 @@ +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + #include "IrisDataDao.h" IrisDataDao::IrisDataDao(QObject *parent) : BaseDao(parent) @@ -37,7 +41,7 @@ result.append(item); } -// LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } @@ -104,7 +108,7 @@ result.insert("right_iris_code3", query.value("right_iris_code3")); } -// LOG_DEBUG(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); + LOG_TRACE(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); return result; } @@ -114,7 +118,12 @@ // 新建查询 QSqlQuery query(ConnectionManager::getInstance()->getConnection()); - qulonglong id = ConnectionManager::getInstance()->generateId(); + qulonglong id; + if (object.contains("id") == true) { + id = object.value("id").toULongLong(); + } else { + id = ConnectionManager::getInstance()->generateId(); + } // INSERT语句 QString sql = QString("INSERT INTO IRIS_DATA (ID, PERSON_ID, ID_CARD_NO, LEFT_IRIS_CODE1, RIGHT_IRIS_CODE1) VALUES (:id, :personId, :idCardNo, :left1, :right1)"); @@ -132,7 +141,7 @@ // 执行插入 bool success = query.exec(); -// LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); + LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); // 结束事务 ConnectionManager::getInstance()->getConnection().commit(); diff --git a/dao/RecognitionRecordsDao.cpp b/dao/RecognitionRecordsDao.cpp index 40db453..d795039 100644 --- a/dao/RecognitionRecordsDao.cpp +++ b/dao/RecognitionRecordsDao.cpp @@ -1,4 +1,4 @@ -#include "RecognitionRecordsDao.h" +#include "RecognitionRecordsDao.h" RecognitionRecordsDao::RecognitionRecordsDao(QObject *parent) : BaseDao(parent) { @@ -58,10 +58,8 @@ query.bindValue(":doorCode", object.value("door_code").toString()); query.bindValue(":inoutType", object.value("inout_type").toString()); -// LOG_DEBUG(sql.toStdString()); - // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES (:id, :logInfo)"); + QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES (:id, :logInfo)"); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/dao/SysDictDao.cpp b/dao/SysDictDao.cpp new file mode 100644 index 0000000..7a2bc8b --- /dev/null +++ b/dao/SysDictDao.cpp @@ -0,0 +1,82 @@ +#include "SysDictDao.h" + + +SysDictDao::SysDictDao(QObject *parent) : BaseDao(parent) +{ + +} + +QVector SysDictDao::findAllRecord() +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT"; + + // 执行查询 + query.exec(sql); + + // 返回结果 + QVector result; + + // 遍历查询结果 + while (query.next()) { + QVariantMap item; + + item.insert("id", query.value("id").toLongLong()); + item.insert("code", query.value("code").toString()); + item.insert("name", query.value("name").toString()); + item.insert("pid", query.value("pid").toString()); + + result.append(item); + } + + return result; +} + +QVariantMap SysDictDao::findRecordById(QString id) +{ + QVariantMap item; + return item; +} + + +QVariantMap SysDictDao::findChildDictByCode(QString code) +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT where PID = (SELECT ID FROM SYS_DICT WHERE CODE = :code)"; + query.prepare(sql); + query.bindValue(":code", code); + + // 执行查询 + query.exec(); + + // 返回结果 + QVariantMap result; + + // 遍历查询结果 + while (query.next()) { + result.insert(query.value("code").toString(), query.value("name").toString()); + } + + return result; +} + +QString SysDictDao::save(QVariantMap object) +{ + return "0"; +} + +bool SysDictDao::edit(QVariantMap newObject, QString id) +{ + return false; +} + +bool SysDictDao::dele(QString id) +{ + return false; +} diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index 1558461..c528381 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -87,9 +87,6 @@ this->cascade->load(cascadeName); } - QElapsedTimer timer; - timer.start(); - std::vector rect; cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); @@ -111,8 +108,8 @@ // .arg(timer.elapsed()).arg(rect.size()) // .arg(rect.at(0).x).arg(rect.at(0).y) // .arg(rect.at(0).width).arg(rect.at(0).height).toStdString()); - qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]") - .arg(timer.elapsed()).arg(rect.size()) + qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]") + .arg(rect.size()) .arg(rect.at(0).x).arg(rect.at(0).y) .arg(rect.at(0).width).arg(rect.at(0).height); @@ -141,20 +138,18 @@ } // 裁剪眼部图像 - cv::Mat halfSize = irisInfo.matData.clone(); - halfSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, + cv::Mat cutSize = irisInfo.matData.clone(); + cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5, SettingConfig::getInstance().IRIS_WIDTH * cutRatio, SettingConfig::getInstance().IRIS_HEIGHT * cutRatio)); - cv::resize(halfSize, halfSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); - cv::flip(halfSize, halfSize, 1); // 左右翻转 + // 裁剪后放大到 640 * 480 + cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); + cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; -// irisInfo.eyeRect = rect.at(0); - - irisInfo.matData = halfSize; -// irisInfo.data = ImageUtil::MatImageToQImage(halfSize); + irisInfo.matData = cutSize; return irisInfo; } @@ -229,9 +224,18 @@ return irisInfo; } +QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo) +{ + QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm); + return irisFeatureCode; +} + float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo) { -// cv::imshow("info", irisInfo.irisCode); -// cv::waitKey(0); return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm); } + +float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other) +{ + return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data())); +} diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index cbee8fe..26fbedc 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -27,7 +27,9 @@ CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); + QByteArray extractFeature(CasicIrisInfo irisInfo); float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo); + float calculatePairPoints(QByteArray feature, QByteArray other); void setCascadeFile(QString filename); void setMinEyeSize(int minEyeSize); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index c8ffe3e..ad456b4 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -177,6 +177,8 @@ // Get the coordinates file >> i; file >> j; + mvApplicationPoints.push_back(QPair(i, j)); + // Set pixel to "on" if (i < 0 || i > applicationPoints.rows - 1 || j < 0 || j > applicationPoints.cols- 1) { @@ -237,7 +239,96 @@ roi.copyTo(dst); //cv::copyTo(img2, dst, NULL); } - return encodeImage; + cv::Mat image8UC1; + encodeImage.convertTo(image8UC1, CV_8UC1); + return image8UC1; +} + +QByteArray CasicIrisRec::extractFeature(cv::Mat irisCode, cv::Mat maskNorm) +{ + // count points width and height + cv::Mat pointTemp(applicationPoints); + cv::Mat rowTemp; + + std::vector pointRows; + for (int i = 0; i < applicationPoints.rows; i++) { + rowTemp = pointTemp(cv::Rect(0, i, applicationPoints.cols, 1)); + if (cv::sum(rowTemp)[0] > 0) { + pointRows.push_back(i); + } + } + + int width = irisCode.cols; + int height = pointRows.size(); + rowTemp.release(); + pointTemp.release(); + + int n_codes = irisCode.rows / applicationPoints.rows; + + int irisDataLength = (n_codes + 1) * width * height; + uchar * irisData = new uchar[irisDataLength]; + int irisDataIndex = 0; + + uchar* codePixel = new uchar; + + // save iris code 512 * 8 * 6 + for (int n = 0; n < n_codes; n++) { // 6 + for (auto i : pointRows) { // 8 + i = n * maskNorm.rows + i; + for (int j = 0; j < irisCode.cols; j++) { // 512 + codePixel = (uchar*)(irisCode.data + i * irisCode.step + j); + if (*codePixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *codePixel; + } + } + } + } + + // save iris mask 512 * 8 * 1 + uchar * maskPixel; + for (auto i : pointRows) { // 8 + for (int j = 0; j < irisCode.cols; j++) { // 512 + maskPixel = (uchar*)(maskNorm.data + i * maskNorm.step + j); + if (*maskPixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *maskPixel; + } + } + } + + + uchar * irisFeaturePtr = new uchar[irisDataLength / 8 + 5]; + memset(irisFeaturePtr, 0, irisDataLength / 8 + 5); + + // first byte is width; + irisFeaturePtr[0] = (uchar)width; + irisFeaturePtr[1] = (uchar)(width >> 8); + + // second byte is height; + irisFeaturePtr[2] = (uchar)height; + + // third byte is n_codes + irisFeaturePtr[3] = (uchar)n_codes; + + // fourth byte is n_mask(1) + irisFeaturePtr[4] = (uchar)1; + for (int i = 0; i < irisDataLength; i++) { + irisFeaturePtr[5 + i / 8] += irisData[i] << (7 - (i % 8)); + } + + QByteArray feature; + for (int i = 0; i < irisDataLength / 8 + 5; i++) { + feature.append((char) irisFeaturePtr[i]); + } + + delete[] irisData; + delete[] irisFeaturePtr; + return feature; } float CasicIrisRec::matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2) @@ -283,6 +374,67 @@ } +float CasicIrisRec::matchFeatureCode(uchar *feature1, uchar *feature2) +{ + int width = feature1[0] | feature1[1] << 8; // 32 + int height = feature1[2]; // 8 + int nCode = feature1[3]; // 6 +// int nMask = feature1[4]; + + uchar ** irisData1 = reduceIrisCode(feature1); + uchar ** irisMask1 = reduceIrisMask(feature1); + uchar ** irisData2 = reduceIrisCode(feature2); + uchar ** irisMask2 = reduceIrisMask(feature2); + + int shift = 10; + float score = 1.0; + + int minstep = 0 - shift; + int maxstep = shift; + + for (int s = minstep; s <= maxstep; s++) { + int count = 0; + float mean = 0.0; + for (int n = 0; n < nCode; n++) { + for (auto pos : mvApplicationPoints) { + int row = pos.first / mvApplicationPoints[0].first - 1; + int col = (pos.second + s + width) % width; + + if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { + + uchar tmp1 = irisData1[row + height * n][col]; + uchar tmp2 = irisData2[row + height * n][pos.second]; + mean += tmp1 ^ tmp2; + count += 1; + } + } + } + + //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; + mean = mean / count; + score = mean < score ? mean : score; + + } + +// std::cout << "feature score: " << score << std::endl; + + +// for (int i = 0; i < height * nCode; i++) { +// delete irisData1[i]; +// delete irisData2[i]; +// } +// delete irisData1; +// delete irisData2; + +// for (int i = 0; i < height; i++) { +// delete irisMask1[i]; +// delete irisMask2[i]; +// } +// delete irisMask1; +// delete irisMask2; + return score; +} + cv::Mat CasicIrisRec::addBorders(cv::Mat pSrc, int width) { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); @@ -298,4 +450,39 @@ return result; } +uchar ** CasicIrisRec::reduceIrisCode(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2] * feature[3]; + + uchar ** reduceCode = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + reduceCode[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = i * width + j; + reduceCode[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return reduceCode; +} + +uchar ** CasicIrisRec::reduceIrisMask(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2]; // 8 + int nCode = feature[3]; // 6 + + uchar ** irisMask = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + irisMask[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = width * height * nCode + i * width + j; + irisMask[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return irisMask; +} + } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index f6ca8ac..2d9616e 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -5,6 +5,8 @@ #define NORM_HEIGHT 64 #define M_PI 3.1415926535897323846 +#include +#include #include namespace iristrt @@ -15,28 +17,28 @@ public: CasicIrisRec(); - CasicIrisRec(const char * gaborFilterFileName,const char * applicationPointsFileName); - ~CasicIrisRec(); cv::Mat normalize(cv::Mat image, int iris_x, int iris_y, int iris_r,int pupil_x, int pupil_y, int pupil_r); - cv::Mat encodeToImage(cv::Mat normalizedImage); + QByteArray extractFeature(cv::Mat irisCode, cv::Mat maskNorm); float matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2); + float matchFeatureCode(uchar * feature1, uchar * feature2); private: std::vector gaborFilters; - cv::Mat applicationPoints; + std::vector> mvApplicationPoints; std::vector loadGaborFilters(const char * gaborFilterFileName); - cv::Mat loadApplicationPoints(const char * applicationPointsFileName); cv::Mat addBorders(cv::Mat pSrc, int width); + uchar ** reduceIrisCode(uchar * feature); + uchar ** reduceIrisMask(uchar * feature); }; // end of class CasicIrisRec diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 37a0ed6..63eda4d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,3 +1,7 @@ +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + #include "IrisDataDao.h" IrisDataDao::IrisDataDao(QObject *parent) : BaseDao(parent) @@ -37,7 +41,7 @@ result.append(item); } -// LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } @@ -104,7 +108,7 @@ result.insert("right_iris_code3", query.value("right_iris_code3")); } -// LOG_DEBUG(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); + LOG_TRACE(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); return result; } @@ -114,7 +118,12 @@ // 新建查询 QSqlQuery query(ConnectionManager::getInstance()->getConnection()); - qulonglong id = ConnectionManager::getInstance()->generateId(); + qulonglong id; + if (object.contains("id") == true) { + id = object.value("id").toULongLong(); + } else { + id = ConnectionManager::getInstance()->generateId(); + } // INSERT语句 QString sql = QString("INSERT INTO IRIS_DATA (ID, PERSON_ID, ID_CARD_NO, LEFT_IRIS_CODE1, RIGHT_IRIS_CODE1) VALUES (:id, :personId, :idCardNo, :left1, :right1)"); @@ -132,7 +141,7 @@ // 执行插入 bool success = query.exec(); -// LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); + LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); // 结束事务 ConnectionManager::getInstance()->getConnection().commit(); diff --git a/dao/RecognitionRecordsDao.cpp b/dao/RecognitionRecordsDao.cpp index 40db453..d795039 100644 --- a/dao/RecognitionRecordsDao.cpp +++ b/dao/RecognitionRecordsDao.cpp @@ -1,4 +1,4 @@ -#include "RecognitionRecordsDao.h" +#include "RecognitionRecordsDao.h" RecognitionRecordsDao::RecognitionRecordsDao(QObject *parent) : BaseDao(parent) { @@ -58,10 +58,8 @@ query.bindValue(":doorCode", object.value("door_code").toString()); query.bindValue(":inoutType", object.value("inout_type").toString()); -// LOG_DEBUG(sql.toStdString()); - // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES (:id, :logInfo)"); + QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES (:id, :logInfo)"); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/dao/SysDictDao.cpp b/dao/SysDictDao.cpp new file mode 100644 index 0000000..7a2bc8b --- /dev/null +++ b/dao/SysDictDao.cpp @@ -0,0 +1,82 @@ +#include "SysDictDao.h" + + +SysDictDao::SysDictDao(QObject *parent) : BaseDao(parent) +{ + +} + +QVector SysDictDao::findAllRecord() +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT"; + + // 执行查询 + query.exec(sql); + + // 返回结果 + QVector result; + + // 遍历查询结果 + while (query.next()) { + QVariantMap item; + + item.insert("id", query.value("id").toLongLong()); + item.insert("code", query.value("code").toString()); + item.insert("name", query.value("name").toString()); + item.insert("pid", query.value("pid").toString()); + + result.append(item); + } + + return result; +} + +QVariantMap SysDictDao::findRecordById(QString id) +{ + QVariantMap item; + return item; +} + + +QVariantMap SysDictDao::findChildDictByCode(QString code) +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT where PID = (SELECT ID FROM SYS_DICT WHERE CODE = :code)"; + query.prepare(sql); + query.bindValue(":code", code); + + // 执行查询 + query.exec(); + + // 返回结果 + QVariantMap result; + + // 遍历查询结果 + while (query.next()) { + result.insert(query.value("code").toString(), query.value("name").toString()); + } + + return result; +} + +QString SysDictDao::save(QVariantMap object) +{ + return "0"; +} + +bool SysDictDao::edit(QVariantMap newObject, QString id) +{ + return false; +} + +bool SysDictDao::dele(QString id) +{ + return false; +} diff --git a/dao/SysDictDao.h b/dao/SysDictDao.h new file mode 100644 index 0000000..7c73aff --- /dev/null +++ b/dao/SysDictDao.h @@ -0,0 +1,23 @@ +#ifndef SYSDICTDAO_H +#define SYSDICTDAO_H + +#include +#include "BaseDao.h" + +class SysDictDao : public BaseDao +{ + Q_OBJECT +public: + explicit SysDictDao(QObject *parent = nullptr); + + QVector findAllRecord(); + QVariantMap findRecordById(QString id); + + QVariantMap findChildDictByCode(QString code); + + QString save(QVariantMap object); + bool edit(QVariantMap newObject, QString id); + bool dele(QString id); +}; + +#endif // SYSDICTDAO_H diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index 1558461..c528381 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -87,9 +87,6 @@ this->cascade->load(cascadeName); } - QElapsedTimer timer; - timer.start(); - std::vector rect; cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); @@ -111,8 +108,8 @@ // .arg(timer.elapsed()).arg(rect.size()) // .arg(rect.at(0).x).arg(rect.at(0).y) // .arg(rect.at(0).width).arg(rect.at(0).height).toStdString()); - qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]") - .arg(timer.elapsed()).arg(rect.size()) + qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]") + .arg(rect.size()) .arg(rect.at(0).x).arg(rect.at(0).y) .arg(rect.at(0).width).arg(rect.at(0).height); @@ -141,20 +138,18 @@ } // 裁剪眼部图像 - cv::Mat halfSize = irisInfo.matData.clone(); - halfSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, + cv::Mat cutSize = irisInfo.matData.clone(); + cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5, SettingConfig::getInstance().IRIS_WIDTH * cutRatio, SettingConfig::getInstance().IRIS_HEIGHT * cutRatio)); - cv::resize(halfSize, halfSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); - cv::flip(halfSize, halfSize, 1); // 左右翻转 + // 裁剪后放大到 640 * 480 + cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); + cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; -// irisInfo.eyeRect = rect.at(0); - - irisInfo.matData = halfSize; -// irisInfo.data = ImageUtil::MatImageToQImage(halfSize); + irisInfo.matData = cutSize; return irisInfo; } @@ -229,9 +224,18 @@ return irisInfo; } +QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo) +{ + QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm); + return irisFeatureCode; +} + float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo) { -// cv::imshow("info", irisInfo.irisCode); -// cv::waitKey(0); return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm); } + +float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other) +{ + return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data())); +} diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index cbee8fe..26fbedc 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -27,7 +27,9 @@ CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); + QByteArray extractFeature(CasicIrisInfo irisInfo); float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo); + float calculatePairPoints(QByteArray feature, QByteArray other); void setCascadeFile(QString filename); void setMinEyeSize(int minEyeSize); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index c8ffe3e..ad456b4 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -177,6 +177,8 @@ // Get the coordinates file >> i; file >> j; + mvApplicationPoints.push_back(QPair(i, j)); + // Set pixel to "on" if (i < 0 || i > applicationPoints.rows - 1 || j < 0 || j > applicationPoints.cols- 1) { @@ -237,7 +239,96 @@ roi.copyTo(dst); //cv::copyTo(img2, dst, NULL); } - return encodeImage; + cv::Mat image8UC1; + encodeImage.convertTo(image8UC1, CV_8UC1); + return image8UC1; +} + +QByteArray CasicIrisRec::extractFeature(cv::Mat irisCode, cv::Mat maskNorm) +{ + // count points width and height + cv::Mat pointTemp(applicationPoints); + cv::Mat rowTemp; + + std::vector pointRows; + for (int i = 0; i < applicationPoints.rows; i++) { + rowTemp = pointTemp(cv::Rect(0, i, applicationPoints.cols, 1)); + if (cv::sum(rowTemp)[0] > 0) { + pointRows.push_back(i); + } + } + + int width = irisCode.cols; + int height = pointRows.size(); + rowTemp.release(); + pointTemp.release(); + + int n_codes = irisCode.rows / applicationPoints.rows; + + int irisDataLength = (n_codes + 1) * width * height; + uchar * irisData = new uchar[irisDataLength]; + int irisDataIndex = 0; + + uchar* codePixel = new uchar; + + // save iris code 512 * 8 * 6 + for (int n = 0; n < n_codes; n++) { // 6 + for (auto i : pointRows) { // 8 + i = n * maskNorm.rows + i; + for (int j = 0; j < irisCode.cols; j++) { // 512 + codePixel = (uchar*)(irisCode.data + i * irisCode.step + j); + if (*codePixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *codePixel; + } + } + } + } + + // save iris mask 512 * 8 * 1 + uchar * maskPixel; + for (auto i : pointRows) { // 8 + for (int j = 0; j < irisCode.cols; j++) { // 512 + maskPixel = (uchar*)(maskNorm.data + i * maskNorm.step + j); + if (*maskPixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *maskPixel; + } + } + } + + + uchar * irisFeaturePtr = new uchar[irisDataLength / 8 + 5]; + memset(irisFeaturePtr, 0, irisDataLength / 8 + 5); + + // first byte is width; + irisFeaturePtr[0] = (uchar)width; + irisFeaturePtr[1] = (uchar)(width >> 8); + + // second byte is height; + irisFeaturePtr[2] = (uchar)height; + + // third byte is n_codes + irisFeaturePtr[3] = (uchar)n_codes; + + // fourth byte is n_mask(1) + irisFeaturePtr[4] = (uchar)1; + for (int i = 0; i < irisDataLength; i++) { + irisFeaturePtr[5 + i / 8] += irisData[i] << (7 - (i % 8)); + } + + QByteArray feature; + for (int i = 0; i < irisDataLength / 8 + 5; i++) { + feature.append((char) irisFeaturePtr[i]); + } + + delete[] irisData; + delete[] irisFeaturePtr; + return feature; } float CasicIrisRec::matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2) @@ -283,6 +374,67 @@ } +float CasicIrisRec::matchFeatureCode(uchar *feature1, uchar *feature2) +{ + int width = feature1[0] | feature1[1] << 8; // 32 + int height = feature1[2]; // 8 + int nCode = feature1[3]; // 6 +// int nMask = feature1[4]; + + uchar ** irisData1 = reduceIrisCode(feature1); + uchar ** irisMask1 = reduceIrisMask(feature1); + uchar ** irisData2 = reduceIrisCode(feature2); + uchar ** irisMask2 = reduceIrisMask(feature2); + + int shift = 10; + float score = 1.0; + + int minstep = 0 - shift; + int maxstep = shift; + + for (int s = minstep; s <= maxstep; s++) { + int count = 0; + float mean = 0.0; + for (int n = 0; n < nCode; n++) { + for (auto pos : mvApplicationPoints) { + int row = pos.first / mvApplicationPoints[0].first - 1; + int col = (pos.second + s + width) % width; + + if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { + + uchar tmp1 = irisData1[row + height * n][col]; + uchar tmp2 = irisData2[row + height * n][pos.second]; + mean += tmp1 ^ tmp2; + count += 1; + } + } + } + + //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; + mean = mean / count; + score = mean < score ? mean : score; + + } + +// std::cout << "feature score: " << score << std::endl; + + +// for (int i = 0; i < height * nCode; i++) { +// delete irisData1[i]; +// delete irisData2[i]; +// } +// delete irisData1; +// delete irisData2; + +// for (int i = 0; i < height; i++) { +// delete irisMask1[i]; +// delete irisMask2[i]; +// } +// delete irisMask1; +// delete irisMask2; + return score; +} + cv::Mat CasicIrisRec::addBorders(cv::Mat pSrc, int width) { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); @@ -298,4 +450,39 @@ return result; } +uchar ** CasicIrisRec::reduceIrisCode(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2] * feature[3]; + + uchar ** reduceCode = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + reduceCode[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = i * width + j; + reduceCode[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return reduceCode; +} + +uchar ** CasicIrisRec::reduceIrisMask(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2]; // 8 + int nCode = feature[3]; // 6 + + uchar ** irisMask = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + irisMask[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = width * height * nCode + i * width + j; + irisMask[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return irisMask; +} + } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index f6ca8ac..2d9616e 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -5,6 +5,8 @@ #define NORM_HEIGHT 64 #define M_PI 3.1415926535897323846 +#include +#include #include namespace iristrt @@ -15,28 +17,28 @@ public: CasicIrisRec(); - CasicIrisRec(const char * gaborFilterFileName,const char * applicationPointsFileName); - ~CasicIrisRec(); cv::Mat normalize(cv::Mat image, int iris_x, int iris_y, int iris_r,int pupil_x, int pupil_y, int pupil_r); - cv::Mat encodeToImage(cv::Mat normalizedImage); + QByteArray extractFeature(cv::Mat irisCode, cv::Mat maskNorm); float matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2); + float matchFeatureCode(uchar * feature1, uchar * feature2); private: std::vector gaborFilters; - cv::Mat applicationPoints; + std::vector> mvApplicationPoints; std::vector loadGaborFilters(const char * gaborFilterFileName); - cv::Mat loadApplicationPoints(const char * applicationPointsFileName); cv::Mat addBorders(cv::Mat pSrc, int width); + uchar ** reduceIrisCode(uchar * feature); + uchar ** reduceIrisMask(uchar * feature); }; // end of class CasicIrisRec diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 37a0ed6..63eda4d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,3 +1,7 @@ +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + #include "IrisDataDao.h" IrisDataDao::IrisDataDao(QObject *parent) : BaseDao(parent) @@ -37,7 +41,7 @@ result.append(item); } -// LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } @@ -104,7 +108,7 @@ result.insert("right_iris_code3", query.value("right_iris_code3")); } -// LOG_DEBUG(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); + LOG_TRACE(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); return result; } @@ -114,7 +118,12 @@ // 新建查询 QSqlQuery query(ConnectionManager::getInstance()->getConnection()); - qulonglong id = ConnectionManager::getInstance()->generateId(); + qulonglong id; + if (object.contains("id") == true) { + id = object.value("id").toULongLong(); + } else { + id = ConnectionManager::getInstance()->generateId(); + } // INSERT语句 QString sql = QString("INSERT INTO IRIS_DATA (ID, PERSON_ID, ID_CARD_NO, LEFT_IRIS_CODE1, RIGHT_IRIS_CODE1) VALUES (:id, :personId, :idCardNo, :left1, :right1)"); @@ -132,7 +141,7 @@ // 执行插入 bool success = query.exec(); -// LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); + LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); // 结束事务 ConnectionManager::getInstance()->getConnection().commit(); diff --git a/dao/RecognitionRecordsDao.cpp b/dao/RecognitionRecordsDao.cpp index 40db453..d795039 100644 --- a/dao/RecognitionRecordsDao.cpp +++ b/dao/RecognitionRecordsDao.cpp @@ -1,4 +1,4 @@ -#include "RecognitionRecordsDao.h" +#include "RecognitionRecordsDao.h" RecognitionRecordsDao::RecognitionRecordsDao(QObject *parent) : BaseDao(parent) { @@ -58,10 +58,8 @@ query.bindValue(":doorCode", object.value("door_code").toString()); query.bindValue(":inoutType", object.value("inout_type").toString()); -// LOG_DEBUG(sql.toStdString()); - // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES (:id, :logInfo)"); + QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES (:id, :logInfo)"); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/dao/SysDictDao.cpp b/dao/SysDictDao.cpp new file mode 100644 index 0000000..7a2bc8b --- /dev/null +++ b/dao/SysDictDao.cpp @@ -0,0 +1,82 @@ +#include "SysDictDao.h" + + +SysDictDao::SysDictDao(QObject *parent) : BaseDao(parent) +{ + +} + +QVector SysDictDao::findAllRecord() +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT"; + + // 执行查询 + query.exec(sql); + + // 返回结果 + QVector result; + + // 遍历查询结果 + while (query.next()) { + QVariantMap item; + + item.insert("id", query.value("id").toLongLong()); + item.insert("code", query.value("code").toString()); + item.insert("name", query.value("name").toString()); + item.insert("pid", query.value("pid").toString()); + + result.append(item); + } + + return result; +} + +QVariantMap SysDictDao::findRecordById(QString id) +{ + QVariantMap item; + return item; +} + + +QVariantMap SysDictDao::findChildDictByCode(QString code) +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT where PID = (SELECT ID FROM SYS_DICT WHERE CODE = :code)"; + query.prepare(sql); + query.bindValue(":code", code); + + // 执行查询 + query.exec(); + + // 返回结果 + QVariantMap result; + + // 遍历查询结果 + while (query.next()) { + result.insert(query.value("code").toString(), query.value("name").toString()); + } + + return result; +} + +QString SysDictDao::save(QVariantMap object) +{ + return "0"; +} + +bool SysDictDao::edit(QVariantMap newObject, QString id) +{ + return false; +} + +bool SysDictDao::dele(QString id) +{ + return false; +} diff --git a/dao/SysDictDao.h b/dao/SysDictDao.h new file mode 100644 index 0000000..7c73aff --- /dev/null +++ b/dao/SysDictDao.h @@ -0,0 +1,23 @@ +#ifndef SYSDICTDAO_H +#define SYSDICTDAO_H + +#include +#include "BaseDao.h" + +class SysDictDao : public BaseDao +{ + Q_OBJECT +public: + explicit SysDictDao(QObject *parent = nullptr); + + QVector findAllRecord(); + QVariantMap findRecordById(QString id); + + QVariantMap findChildDictByCode(QString code); + + QString save(QVariantMap object); + bool edit(QVariantMap newObject, QString id); + bool dele(QString id); +}; + +#endif // SYSDICTDAO_H diff --git a/dao/SysPersonDao.cpp b/dao/SysPersonDao.cpp index dd9480f..19243b1 100644 --- a/dao/SysPersonDao.cpp +++ b/dao/SysPersonDao.cpp @@ -1,4 +1,4 @@ -#include "SysPersonDao.h" +#include "SysPersonDao.h" SysPersonDao::SysPersonDao(QObject *parent) : BaseDao(parent) @@ -56,10 +56,13 @@ QSqlQuery query(ConnectionManager::getInstance()->getConnection()); // 查询语句 - QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = '%1'").arg(id); + QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = :id"); + + query.prepare(sql); + query.bindValue(":id", id); // 执行查询 - query.exec(sql); + query.exec(); // 返回结果 QVariantMap result; @@ -84,8 +87,9 @@ result.insert("person_code", query.value("person_code").toString()); result.insert("deptname", query.value("fullname").toString()); result.insert("sync_id", query.value("sync_id").toString()); - result.insert("hasFace", query.value("face_valid").toString()); - result.insert("hasIris", query.value("iris_valid").toString()); + result.insert("avatar", query.value("avatar").toString()); +// result.insert("hasFace", query.value("face_valid").toString()); +// result.insert("hasIris", query.value("iris_valid").toString()); } // LOG(TRACE) << QString("根据id查询SYS_PERSON表的记录[id=%1][%2]").arg(id).arg(sql).toStdString(); diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index 1558461..c528381 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -87,9 +87,6 @@ this->cascade->load(cascadeName); } - QElapsedTimer timer; - timer.start(); - std::vector rect; cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); @@ -111,8 +108,8 @@ // .arg(timer.elapsed()).arg(rect.size()) // .arg(rect.at(0).x).arg(rect.at(0).y) // .arg(rect.at(0).width).arg(rect.at(0).height).toStdString()); - qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]") - .arg(timer.elapsed()).arg(rect.size()) + qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]") + .arg(rect.size()) .arg(rect.at(0).x).arg(rect.at(0).y) .arg(rect.at(0).width).arg(rect.at(0).height); @@ -141,20 +138,18 @@ } // 裁剪眼部图像 - cv::Mat halfSize = irisInfo.matData.clone(); - halfSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, + cv::Mat cutSize = irisInfo.matData.clone(); + cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5, SettingConfig::getInstance().IRIS_WIDTH * cutRatio, SettingConfig::getInstance().IRIS_HEIGHT * cutRatio)); - cv::resize(halfSize, halfSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); - cv::flip(halfSize, halfSize, 1); // 左右翻转 + // 裁剪后放大到 640 * 480 + cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); + cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; -// irisInfo.eyeRect = rect.at(0); - - irisInfo.matData = halfSize; -// irisInfo.data = ImageUtil::MatImageToQImage(halfSize); + irisInfo.matData = cutSize; return irisInfo; } @@ -229,9 +224,18 @@ return irisInfo; } +QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo) +{ + QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm); + return irisFeatureCode; +} + float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo) { -// cv::imshow("info", irisInfo.irisCode); -// cv::waitKey(0); return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm); } + +float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other) +{ + return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data())); +} diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index cbee8fe..26fbedc 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -27,7 +27,9 @@ CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); + QByteArray extractFeature(CasicIrisInfo irisInfo); float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo); + float calculatePairPoints(QByteArray feature, QByteArray other); void setCascadeFile(QString filename); void setMinEyeSize(int minEyeSize); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index c8ffe3e..ad456b4 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -177,6 +177,8 @@ // Get the coordinates file >> i; file >> j; + mvApplicationPoints.push_back(QPair(i, j)); + // Set pixel to "on" if (i < 0 || i > applicationPoints.rows - 1 || j < 0 || j > applicationPoints.cols- 1) { @@ -237,7 +239,96 @@ roi.copyTo(dst); //cv::copyTo(img2, dst, NULL); } - return encodeImage; + cv::Mat image8UC1; + encodeImage.convertTo(image8UC1, CV_8UC1); + return image8UC1; +} + +QByteArray CasicIrisRec::extractFeature(cv::Mat irisCode, cv::Mat maskNorm) +{ + // count points width and height + cv::Mat pointTemp(applicationPoints); + cv::Mat rowTemp; + + std::vector pointRows; + for (int i = 0; i < applicationPoints.rows; i++) { + rowTemp = pointTemp(cv::Rect(0, i, applicationPoints.cols, 1)); + if (cv::sum(rowTemp)[0] > 0) { + pointRows.push_back(i); + } + } + + int width = irisCode.cols; + int height = pointRows.size(); + rowTemp.release(); + pointTemp.release(); + + int n_codes = irisCode.rows / applicationPoints.rows; + + int irisDataLength = (n_codes + 1) * width * height; + uchar * irisData = new uchar[irisDataLength]; + int irisDataIndex = 0; + + uchar* codePixel = new uchar; + + // save iris code 512 * 8 * 6 + for (int n = 0; n < n_codes; n++) { // 6 + for (auto i : pointRows) { // 8 + i = n * maskNorm.rows + i; + for (int j = 0; j < irisCode.cols; j++) { // 512 + codePixel = (uchar*)(irisCode.data + i * irisCode.step + j); + if (*codePixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *codePixel; + } + } + } + } + + // save iris mask 512 * 8 * 1 + uchar * maskPixel; + for (auto i : pointRows) { // 8 + for (int j = 0; j < irisCode.cols; j++) { // 512 + maskPixel = (uchar*)(maskNorm.data + i * maskNorm.step + j); + if (*maskPixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *maskPixel; + } + } + } + + + uchar * irisFeaturePtr = new uchar[irisDataLength / 8 + 5]; + memset(irisFeaturePtr, 0, irisDataLength / 8 + 5); + + // first byte is width; + irisFeaturePtr[0] = (uchar)width; + irisFeaturePtr[1] = (uchar)(width >> 8); + + // second byte is height; + irisFeaturePtr[2] = (uchar)height; + + // third byte is n_codes + irisFeaturePtr[3] = (uchar)n_codes; + + // fourth byte is n_mask(1) + irisFeaturePtr[4] = (uchar)1; + for (int i = 0; i < irisDataLength; i++) { + irisFeaturePtr[5 + i / 8] += irisData[i] << (7 - (i % 8)); + } + + QByteArray feature; + for (int i = 0; i < irisDataLength / 8 + 5; i++) { + feature.append((char) irisFeaturePtr[i]); + } + + delete[] irisData; + delete[] irisFeaturePtr; + return feature; } float CasicIrisRec::matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2) @@ -283,6 +374,67 @@ } +float CasicIrisRec::matchFeatureCode(uchar *feature1, uchar *feature2) +{ + int width = feature1[0] | feature1[1] << 8; // 32 + int height = feature1[2]; // 8 + int nCode = feature1[3]; // 6 +// int nMask = feature1[4]; + + uchar ** irisData1 = reduceIrisCode(feature1); + uchar ** irisMask1 = reduceIrisMask(feature1); + uchar ** irisData2 = reduceIrisCode(feature2); + uchar ** irisMask2 = reduceIrisMask(feature2); + + int shift = 10; + float score = 1.0; + + int minstep = 0 - shift; + int maxstep = shift; + + for (int s = minstep; s <= maxstep; s++) { + int count = 0; + float mean = 0.0; + for (int n = 0; n < nCode; n++) { + for (auto pos : mvApplicationPoints) { + int row = pos.first / mvApplicationPoints[0].first - 1; + int col = (pos.second + s + width) % width; + + if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { + + uchar tmp1 = irisData1[row + height * n][col]; + uchar tmp2 = irisData2[row + height * n][pos.second]; + mean += tmp1 ^ tmp2; + count += 1; + } + } + } + + //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; + mean = mean / count; + score = mean < score ? mean : score; + + } + +// std::cout << "feature score: " << score << std::endl; + + +// for (int i = 0; i < height * nCode; i++) { +// delete irisData1[i]; +// delete irisData2[i]; +// } +// delete irisData1; +// delete irisData2; + +// for (int i = 0; i < height; i++) { +// delete irisMask1[i]; +// delete irisMask2[i]; +// } +// delete irisMask1; +// delete irisMask2; + return score; +} + cv::Mat CasicIrisRec::addBorders(cv::Mat pSrc, int width) { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); @@ -298,4 +450,39 @@ return result; } +uchar ** CasicIrisRec::reduceIrisCode(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2] * feature[3]; + + uchar ** reduceCode = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + reduceCode[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = i * width + j; + reduceCode[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return reduceCode; +} + +uchar ** CasicIrisRec::reduceIrisMask(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2]; // 8 + int nCode = feature[3]; // 6 + + uchar ** irisMask = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + irisMask[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = width * height * nCode + i * width + j; + irisMask[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return irisMask; +} + } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index f6ca8ac..2d9616e 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -5,6 +5,8 @@ #define NORM_HEIGHT 64 #define M_PI 3.1415926535897323846 +#include +#include #include namespace iristrt @@ -15,28 +17,28 @@ public: CasicIrisRec(); - CasicIrisRec(const char * gaborFilterFileName,const char * applicationPointsFileName); - ~CasicIrisRec(); cv::Mat normalize(cv::Mat image, int iris_x, int iris_y, int iris_r,int pupil_x, int pupil_y, int pupil_r); - cv::Mat encodeToImage(cv::Mat normalizedImage); + QByteArray extractFeature(cv::Mat irisCode, cv::Mat maskNorm); float matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2); + float matchFeatureCode(uchar * feature1, uchar * feature2); private: std::vector gaborFilters; - cv::Mat applicationPoints; + std::vector> mvApplicationPoints; std::vector loadGaborFilters(const char * gaborFilterFileName); - cv::Mat loadApplicationPoints(const char * applicationPointsFileName); cv::Mat addBorders(cv::Mat pSrc, int width); + uchar ** reduceIrisCode(uchar * feature); + uchar ** reduceIrisMask(uchar * feature); }; // end of class CasicIrisRec diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 37a0ed6..63eda4d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,3 +1,7 @@ +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + #include "IrisDataDao.h" IrisDataDao::IrisDataDao(QObject *parent) : BaseDao(parent) @@ -37,7 +41,7 @@ result.append(item); } -// LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } @@ -104,7 +108,7 @@ result.insert("right_iris_code3", query.value("right_iris_code3")); } -// LOG_DEBUG(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); + LOG_TRACE(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); return result; } @@ -114,7 +118,12 @@ // 新建查询 QSqlQuery query(ConnectionManager::getInstance()->getConnection()); - qulonglong id = ConnectionManager::getInstance()->generateId(); + qulonglong id; + if (object.contains("id") == true) { + id = object.value("id").toULongLong(); + } else { + id = ConnectionManager::getInstance()->generateId(); + } // INSERT语句 QString sql = QString("INSERT INTO IRIS_DATA (ID, PERSON_ID, ID_CARD_NO, LEFT_IRIS_CODE1, RIGHT_IRIS_CODE1) VALUES (:id, :personId, :idCardNo, :left1, :right1)"); @@ -132,7 +141,7 @@ // 执行插入 bool success = query.exec(); -// LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); + LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); // 结束事务 ConnectionManager::getInstance()->getConnection().commit(); diff --git a/dao/RecognitionRecordsDao.cpp b/dao/RecognitionRecordsDao.cpp index 40db453..d795039 100644 --- a/dao/RecognitionRecordsDao.cpp +++ b/dao/RecognitionRecordsDao.cpp @@ -1,4 +1,4 @@ -#include "RecognitionRecordsDao.h" +#include "RecognitionRecordsDao.h" RecognitionRecordsDao::RecognitionRecordsDao(QObject *parent) : BaseDao(parent) { @@ -58,10 +58,8 @@ query.bindValue(":doorCode", object.value("door_code").toString()); query.bindValue(":inoutType", object.value("inout_type").toString()); -// LOG_DEBUG(sql.toStdString()); - // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES (:id, :logInfo)"); + QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES (:id, :logInfo)"); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/dao/SysDictDao.cpp b/dao/SysDictDao.cpp new file mode 100644 index 0000000..7a2bc8b --- /dev/null +++ b/dao/SysDictDao.cpp @@ -0,0 +1,82 @@ +#include "SysDictDao.h" + + +SysDictDao::SysDictDao(QObject *parent) : BaseDao(parent) +{ + +} + +QVector SysDictDao::findAllRecord() +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT"; + + // 执行查询 + query.exec(sql); + + // 返回结果 + QVector result; + + // 遍历查询结果 + while (query.next()) { + QVariantMap item; + + item.insert("id", query.value("id").toLongLong()); + item.insert("code", query.value("code").toString()); + item.insert("name", query.value("name").toString()); + item.insert("pid", query.value("pid").toString()); + + result.append(item); + } + + return result; +} + +QVariantMap SysDictDao::findRecordById(QString id) +{ + QVariantMap item; + return item; +} + + +QVariantMap SysDictDao::findChildDictByCode(QString code) +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT where PID = (SELECT ID FROM SYS_DICT WHERE CODE = :code)"; + query.prepare(sql); + query.bindValue(":code", code); + + // 执行查询 + query.exec(); + + // 返回结果 + QVariantMap result; + + // 遍历查询结果 + while (query.next()) { + result.insert(query.value("code").toString(), query.value("name").toString()); + } + + return result; +} + +QString SysDictDao::save(QVariantMap object) +{ + return "0"; +} + +bool SysDictDao::edit(QVariantMap newObject, QString id) +{ + return false; +} + +bool SysDictDao::dele(QString id) +{ + return false; +} diff --git a/dao/SysDictDao.h b/dao/SysDictDao.h new file mode 100644 index 0000000..7c73aff --- /dev/null +++ b/dao/SysDictDao.h @@ -0,0 +1,23 @@ +#ifndef SYSDICTDAO_H +#define SYSDICTDAO_H + +#include +#include "BaseDao.h" + +class SysDictDao : public BaseDao +{ + Q_OBJECT +public: + explicit SysDictDao(QObject *parent = nullptr); + + QVector findAllRecord(); + QVariantMap findRecordById(QString id); + + QVariantMap findChildDictByCode(QString code); + + QString save(QVariantMap object); + bool edit(QVariantMap newObject, QString id); + bool dele(QString id); +}; + +#endif // SYSDICTDAO_H diff --git a/dao/SysPersonDao.cpp b/dao/SysPersonDao.cpp index dd9480f..19243b1 100644 --- a/dao/SysPersonDao.cpp +++ b/dao/SysPersonDao.cpp @@ -1,4 +1,4 @@ -#include "SysPersonDao.h" +#include "SysPersonDao.h" SysPersonDao::SysPersonDao(QObject *parent) : BaseDao(parent) @@ -56,10 +56,13 @@ QSqlQuery query(ConnectionManager::getInstance()->getConnection()); // 查询语句 - QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = '%1'").arg(id); + QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = :id"); + + query.prepare(sql); + query.bindValue(":id", id); // 执行查询 - query.exec(sql); + query.exec(); // 返回结果 QVariantMap result; @@ -84,8 +87,9 @@ result.insert("person_code", query.value("person_code").toString()); result.insert("deptname", query.value("fullname").toString()); result.insert("sync_id", query.value("sync_id").toString()); - result.insert("hasFace", query.value("face_valid").toString()); - result.insert("hasIris", query.value("iris_valid").toString()); + result.insert("avatar", query.value("avatar").toString()); +// result.insert("hasFace", query.value("face_valid").toString()); +// result.insert("hasIris", query.value("iris_valid").toString()); } // LOG(TRACE) << QString("根据id查询SYS_PERSON表的记录[id=%1][%2]").arg(id).arg(sql).toStdString(); diff --git a/dao/dao.pri b/dao/dao.pri index 1e04ce4..5f3b7f3 100644 --- a/dao/dao.pri +++ b/dao/dao.pri @@ -4,15 +4,17 @@ HEADERS += $$PWD/RecognitionRecordsDao.h HEADERS += $$PWD/SysPersonDao.h HEADERS += $$PWD/SysDeptDao.h +HEADERS += $$PWD/SysDictDao.h SOURCES += $$PWD/BaseDao.cpp SOURCES += $$PWD/IrisDataDao.cpp SOURCES += $$PWD/RecognitionRecordsDao.cpp SOURCES += $$PWD/SysPersonDao.cpp SOURCES += $$PWD/SysDeptDao.cpp +SOURCES += $$PWD/SysDictDao.cpp HEADERS += $$PWD/util/ConnectionManager.h SOURCES += $$PWD/util/ConnectionManager.cpp -#HEADERS += $$PWD/util/CacheManager.h -#SOURCES += $$PWD/util/CacheManager.cpp +HEADERS += $$PWD/util/CacheManager.h +SOURCES += $$PWD/util/CacheManager.cpp diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index 1558461..c528381 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -87,9 +87,6 @@ this->cascade->load(cascadeName); } - QElapsedTimer timer; - timer.start(); - std::vector rect; cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); @@ -111,8 +108,8 @@ // .arg(timer.elapsed()).arg(rect.size()) // .arg(rect.at(0).x).arg(rect.at(0).y) // .arg(rect.at(0).width).arg(rect.at(0).height).toStdString()); - qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]") - .arg(timer.elapsed()).arg(rect.size()) + qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]") + .arg(rect.size()) .arg(rect.at(0).x).arg(rect.at(0).y) .arg(rect.at(0).width).arg(rect.at(0).height); @@ -141,20 +138,18 @@ } // 裁剪眼部图像 - cv::Mat halfSize = irisInfo.matData.clone(); - halfSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, + cv::Mat cutSize = irisInfo.matData.clone(); + cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5, SettingConfig::getInstance().IRIS_WIDTH * cutRatio, SettingConfig::getInstance().IRIS_HEIGHT * cutRatio)); - cv::resize(halfSize, halfSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); - cv::flip(halfSize, halfSize, 1); // 左右翻转 + // 裁剪后放大到 640 * 480 + cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); + cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; -// irisInfo.eyeRect = rect.at(0); - - irisInfo.matData = halfSize; -// irisInfo.data = ImageUtil::MatImageToQImage(halfSize); + irisInfo.matData = cutSize; return irisInfo; } @@ -229,9 +224,18 @@ return irisInfo; } +QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo) +{ + QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm); + return irisFeatureCode; +} + float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo) { -// cv::imshow("info", irisInfo.irisCode); -// cv::waitKey(0); return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm); } + +float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other) +{ + return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data())); +} diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index cbee8fe..26fbedc 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -27,7 +27,9 @@ CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); + QByteArray extractFeature(CasicIrisInfo irisInfo); float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo); + float calculatePairPoints(QByteArray feature, QByteArray other); void setCascadeFile(QString filename); void setMinEyeSize(int minEyeSize); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index c8ffe3e..ad456b4 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -177,6 +177,8 @@ // Get the coordinates file >> i; file >> j; + mvApplicationPoints.push_back(QPair(i, j)); + // Set pixel to "on" if (i < 0 || i > applicationPoints.rows - 1 || j < 0 || j > applicationPoints.cols- 1) { @@ -237,7 +239,96 @@ roi.copyTo(dst); //cv::copyTo(img2, dst, NULL); } - return encodeImage; + cv::Mat image8UC1; + encodeImage.convertTo(image8UC1, CV_8UC1); + return image8UC1; +} + +QByteArray CasicIrisRec::extractFeature(cv::Mat irisCode, cv::Mat maskNorm) +{ + // count points width and height + cv::Mat pointTemp(applicationPoints); + cv::Mat rowTemp; + + std::vector pointRows; + for (int i = 0; i < applicationPoints.rows; i++) { + rowTemp = pointTemp(cv::Rect(0, i, applicationPoints.cols, 1)); + if (cv::sum(rowTemp)[0] > 0) { + pointRows.push_back(i); + } + } + + int width = irisCode.cols; + int height = pointRows.size(); + rowTemp.release(); + pointTemp.release(); + + int n_codes = irisCode.rows / applicationPoints.rows; + + int irisDataLength = (n_codes + 1) * width * height; + uchar * irisData = new uchar[irisDataLength]; + int irisDataIndex = 0; + + uchar* codePixel = new uchar; + + // save iris code 512 * 8 * 6 + for (int n = 0; n < n_codes; n++) { // 6 + for (auto i : pointRows) { // 8 + i = n * maskNorm.rows + i; + for (int j = 0; j < irisCode.cols; j++) { // 512 + codePixel = (uchar*)(irisCode.data + i * irisCode.step + j); + if (*codePixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *codePixel; + } + } + } + } + + // save iris mask 512 * 8 * 1 + uchar * maskPixel; + for (auto i : pointRows) { // 8 + for (int j = 0; j < irisCode.cols; j++) { // 512 + maskPixel = (uchar*)(maskNorm.data + i * maskNorm.step + j); + if (*maskPixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *maskPixel; + } + } + } + + + uchar * irisFeaturePtr = new uchar[irisDataLength / 8 + 5]; + memset(irisFeaturePtr, 0, irisDataLength / 8 + 5); + + // first byte is width; + irisFeaturePtr[0] = (uchar)width; + irisFeaturePtr[1] = (uchar)(width >> 8); + + // second byte is height; + irisFeaturePtr[2] = (uchar)height; + + // third byte is n_codes + irisFeaturePtr[3] = (uchar)n_codes; + + // fourth byte is n_mask(1) + irisFeaturePtr[4] = (uchar)1; + for (int i = 0; i < irisDataLength; i++) { + irisFeaturePtr[5 + i / 8] += irisData[i] << (7 - (i % 8)); + } + + QByteArray feature; + for (int i = 0; i < irisDataLength / 8 + 5; i++) { + feature.append((char) irisFeaturePtr[i]); + } + + delete[] irisData; + delete[] irisFeaturePtr; + return feature; } float CasicIrisRec::matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2) @@ -283,6 +374,67 @@ } +float CasicIrisRec::matchFeatureCode(uchar *feature1, uchar *feature2) +{ + int width = feature1[0] | feature1[1] << 8; // 32 + int height = feature1[2]; // 8 + int nCode = feature1[3]; // 6 +// int nMask = feature1[4]; + + uchar ** irisData1 = reduceIrisCode(feature1); + uchar ** irisMask1 = reduceIrisMask(feature1); + uchar ** irisData2 = reduceIrisCode(feature2); + uchar ** irisMask2 = reduceIrisMask(feature2); + + int shift = 10; + float score = 1.0; + + int minstep = 0 - shift; + int maxstep = shift; + + for (int s = minstep; s <= maxstep; s++) { + int count = 0; + float mean = 0.0; + for (int n = 0; n < nCode; n++) { + for (auto pos : mvApplicationPoints) { + int row = pos.first / mvApplicationPoints[0].first - 1; + int col = (pos.second + s + width) % width; + + if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { + + uchar tmp1 = irisData1[row + height * n][col]; + uchar tmp2 = irisData2[row + height * n][pos.second]; + mean += tmp1 ^ tmp2; + count += 1; + } + } + } + + //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; + mean = mean / count; + score = mean < score ? mean : score; + + } + +// std::cout << "feature score: " << score << std::endl; + + +// for (int i = 0; i < height * nCode; i++) { +// delete irisData1[i]; +// delete irisData2[i]; +// } +// delete irisData1; +// delete irisData2; + +// for (int i = 0; i < height; i++) { +// delete irisMask1[i]; +// delete irisMask2[i]; +// } +// delete irisMask1; +// delete irisMask2; + return score; +} + cv::Mat CasicIrisRec::addBorders(cv::Mat pSrc, int width) { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); @@ -298,4 +450,39 @@ return result; } +uchar ** CasicIrisRec::reduceIrisCode(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2] * feature[3]; + + uchar ** reduceCode = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + reduceCode[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = i * width + j; + reduceCode[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return reduceCode; +} + +uchar ** CasicIrisRec::reduceIrisMask(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2]; // 8 + int nCode = feature[3]; // 6 + + uchar ** irisMask = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + irisMask[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = width * height * nCode + i * width + j; + irisMask[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return irisMask; +} + } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index f6ca8ac..2d9616e 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -5,6 +5,8 @@ #define NORM_HEIGHT 64 #define M_PI 3.1415926535897323846 +#include +#include #include namespace iristrt @@ -15,28 +17,28 @@ public: CasicIrisRec(); - CasicIrisRec(const char * gaborFilterFileName,const char * applicationPointsFileName); - ~CasicIrisRec(); cv::Mat normalize(cv::Mat image, int iris_x, int iris_y, int iris_r,int pupil_x, int pupil_y, int pupil_r); - cv::Mat encodeToImage(cv::Mat normalizedImage); + QByteArray extractFeature(cv::Mat irisCode, cv::Mat maskNorm); float matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2); + float matchFeatureCode(uchar * feature1, uchar * feature2); private: std::vector gaborFilters; - cv::Mat applicationPoints; + std::vector> mvApplicationPoints; std::vector loadGaborFilters(const char * gaborFilterFileName); - cv::Mat loadApplicationPoints(const char * applicationPointsFileName); cv::Mat addBorders(cv::Mat pSrc, int width); + uchar ** reduceIrisCode(uchar * feature); + uchar ** reduceIrisMask(uchar * feature); }; // end of class CasicIrisRec diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 37a0ed6..63eda4d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,3 +1,7 @@ +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + #include "IrisDataDao.h" IrisDataDao::IrisDataDao(QObject *parent) : BaseDao(parent) @@ -37,7 +41,7 @@ result.append(item); } -// LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } @@ -104,7 +108,7 @@ result.insert("right_iris_code3", query.value("right_iris_code3")); } -// LOG_DEBUG(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); + LOG_TRACE(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); return result; } @@ -114,7 +118,12 @@ // 新建查询 QSqlQuery query(ConnectionManager::getInstance()->getConnection()); - qulonglong id = ConnectionManager::getInstance()->generateId(); + qulonglong id; + if (object.contains("id") == true) { + id = object.value("id").toULongLong(); + } else { + id = ConnectionManager::getInstance()->generateId(); + } // INSERT语句 QString sql = QString("INSERT INTO IRIS_DATA (ID, PERSON_ID, ID_CARD_NO, LEFT_IRIS_CODE1, RIGHT_IRIS_CODE1) VALUES (:id, :personId, :idCardNo, :left1, :right1)"); @@ -132,7 +141,7 @@ // 执行插入 bool success = query.exec(); -// LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); + LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); // 结束事务 ConnectionManager::getInstance()->getConnection().commit(); diff --git a/dao/RecognitionRecordsDao.cpp b/dao/RecognitionRecordsDao.cpp index 40db453..d795039 100644 --- a/dao/RecognitionRecordsDao.cpp +++ b/dao/RecognitionRecordsDao.cpp @@ -1,4 +1,4 @@ -#include "RecognitionRecordsDao.h" +#include "RecognitionRecordsDao.h" RecognitionRecordsDao::RecognitionRecordsDao(QObject *parent) : BaseDao(parent) { @@ -58,10 +58,8 @@ query.bindValue(":doorCode", object.value("door_code").toString()); query.bindValue(":inoutType", object.value("inout_type").toString()); -// LOG_DEBUG(sql.toStdString()); - // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES (:id, :logInfo)"); + QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES (:id, :logInfo)"); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/dao/SysDictDao.cpp b/dao/SysDictDao.cpp new file mode 100644 index 0000000..7a2bc8b --- /dev/null +++ b/dao/SysDictDao.cpp @@ -0,0 +1,82 @@ +#include "SysDictDao.h" + + +SysDictDao::SysDictDao(QObject *parent) : BaseDao(parent) +{ + +} + +QVector SysDictDao::findAllRecord() +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT"; + + // 执行查询 + query.exec(sql); + + // 返回结果 + QVector result; + + // 遍历查询结果 + while (query.next()) { + QVariantMap item; + + item.insert("id", query.value("id").toLongLong()); + item.insert("code", query.value("code").toString()); + item.insert("name", query.value("name").toString()); + item.insert("pid", query.value("pid").toString()); + + result.append(item); + } + + return result; +} + +QVariantMap SysDictDao::findRecordById(QString id) +{ + QVariantMap item; + return item; +} + + +QVariantMap SysDictDao::findChildDictByCode(QString code) +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT where PID = (SELECT ID FROM SYS_DICT WHERE CODE = :code)"; + query.prepare(sql); + query.bindValue(":code", code); + + // 执行查询 + query.exec(); + + // 返回结果 + QVariantMap result; + + // 遍历查询结果 + while (query.next()) { + result.insert(query.value("code").toString(), query.value("name").toString()); + } + + return result; +} + +QString SysDictDao::save(QVariantMap object) +{ + return "0"; +} + +bool SysDictDao::edit(QVariantMap newObject, QString id) +{ + return false; +} + +bool SysDictDao::dele(QString id) +{ + return false; +} diff --git a/dao/SysDictDao.h b/dao/SysDictDao.h new file mode 100644 index 0000000..7c73aff --- /dev/null +++ b/dao/SysDictDao.h @@ -0,0 +1,23 @@ +#ifndef SYSDICTDAO_H +#define SYSDICTDAO_H + +#include +#include "BaseDao.h" + +class SysDictDao : public BaseDao +{ + Q_OBJECT +public: + explicit SysDictDao(QObject *parent = nullptr); + + QVector findAllRecord(); + QVariantMap findRecordById(QString id); + + QVariantMap findChildDictByCode(QString code); + + QString save(QVariantMap object); + bool edit(QVariantMap newObject, QString id); + bool dele(QString id); +}; + +#endif // SYSDICTDAO_H diff --git a/dao/SysPersonDao.cpp b/dao/SysPersonDao.cpp index dd9480f..19243b1 100644 --- a/dao/SysPersonDao.cpp +++ b/dao/SysPersonDao.cpp @@ -1,4 +1,4 @@ -#include "SysPersonDao.h" +#include "SysPersonDao.h" SysPersonDao::SysPersonDao(QObject *parent) : BaseDao(parent) @@ -56,10 +56,13 @@ QSqlQuery query(ConnectionManager::getInstance()->getConnection()); // 查询语句 - QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = '%1'").arg(id); + QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = :id"); + + query.prepare(sql); + query.bindValue(":id", id); // 执行查询 - query.exec(sql); + query.exec(); // 返回结果 QVariantMap result; @@ -84,8 +87,9 @@ result.insert("person_code", query.value("person_code").toString()); result.insert("deptname", query.value("fullname").toString()); result.insert("sync_id", query.value("sync_id").toString()); - result.insert("hasFace", query.value("face_valid").toString()); - result.insert("hasIris", query.value("iris_valid").toString()); + result.insert("avatar", query.value("avatar").toString()); +// result.insert("hasFace", query.value("face_valid").toString()); +// result.insert("hasIris", query.value("iris_valid").toString()); } // LOG(TRACE) << QString("根据id查询SYS_PERSON表的记录[id=%1][%2]").arg(id).arg(sql).toStdString(); diff --git a/dao/dao.pri b/dao/dao.pri index 1e04ce4..5f3b7f3 100644 --- a/dao/dao.pri +++ b/dao/dao.pri @@ -4,15 +4,17 @@ HEADERS += $$PWD/RecognitionRecordsDao.h HEADERS += $$PWD/SysPersonDao.h HEADERS += $$PWD/SysDeptDao.h +HEADERS += $$PWD/SysDictDao.h SOURCES += $$PWD/BaseDao.cpp SOURCES += $$PWD/IrisDataDao.cpp SOURCES += $$PWD/RecognitionRecordsDao.cpp SOURCES += $$PWD/SysPersonDao.cpp SOURCES += $$PWD/SysDeptDao.cpp +SOURCES += $$PWD/SysDictDao.cpp HEADERS += $$PWD/util/ConnectionManager.h SOURCES += $$PWD/util/ConnectionManager.cpp -#HEADERS += $$PWD/util/CacheManager.h -#SOURCES += $$PWD/util/CacheManager.cpp +HEADERS += $$PWD/util/CacheManager.h +SOURCES += $$PWD/util/CacheManager.cpp diff --git a/dao/util/CacheManager.cpp b/dao/util/CacheManager.cpp new file mode 100644 index 0000000..e415d93 --- /dev/null +++ b/dao/util/CacheManager.cpp @@ -0,0 +1,12 @@ +#include "CacheManager.h" + +CacheManager::CacheManager() +{ + SysDictDao dictDao; + genderName = dictDao.findChildDictByCode("gender"); +} + +QVariantMap CacheManager::getGenderName() +{ + return genderName; +} diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index 1558461..c528381 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -87,9 +87,6 @@ this->cascade->load(cascadeName); } - QElapsedTimer timer; - timer.start(); - std::vector rect; cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); @@ -111,8 +108,8 @@ // .arg(timer.elapsed()).arg(rect.size()) // .arg(rect.at(0).x).arg(rect.at(0).y) // .arg(rect.at(0).width).arg(rect.at(0).height).toStdString()); - qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]") - .arg(timer.elapsed()).arg(rect.size()) + qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]") + .arg(rect.size()) .arg(rect.at(0).x).arg(rect.at(0).y) .arg(rect.at(0).width).arg(rect.at(0).height); @@ -141,20 +138,18 @@ } // 裁剪眼部图像 - cv::Mat halfSize = irisInfo.matData.clone(); - halfSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, + cv::Mat cutSize = irisInfo.matData.clone(); + cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5, SettingConfig::getInstance().IRIS_WIDTH * cutRatio, SettingConfig::getInstance().IRIS_HEIGHT * cutRatio)); - cv::resize(halfSize, halfSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); - cv::flip(halfSize, halfSize, 1); // 左右翻转 + // 裁剪后放大到 640 * 480 + cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); + cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; -// irisInfo.eyeRect = rect.at(0); - - irisInfo.matData = halfSize; -// irisInfo.data = ImageUtil::MatImageToQImage(halfSize); + irisInfo.matData = cutSize; return irisInfo; } @@ -229,9 +224,18 @@ return irisInfo; } +QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo) +{ + QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm); + return irisFeatureCode; +} + float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo) { -// cv::imshow("info", irisInfo.irisCode); -// cv::waitKey(0); return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm); } + +float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other) +{ + return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data())); +} diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index cbee8fe..26fbedc 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -27,7 +27,9 @@ CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); + QByteArray extractFeature(CasicIrisInfo irisInfo); float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo); + float calculatePairPoints(QByteArray feature, QByteArray other); void setCascadeFile(QString filename); void setMinEyeSize(int minEyeSize); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index c8ffe3e..ad456b4 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -177,6 +177,8 @@ // Get the coordinates file >> i; file >> j; + mvApplicationPoints.push_back(QPair(i, j)); + // Set pixel to "on" if (i < 0 || i > applicationPoints.rows - 1 || j < 0 || j > applicationPoints.cols- 1) { @@ -237,7 +239,96 @@ roi.copyTo(dst); //cv::copyTo(img2, dst, NULL); } - return encodeImage; + cv::Mat image8UC1; + encodeImage.convertTo(image8UC1, CV_8UC1); + return image8UC1; +} + +QByteArray CasicIrisRec::extractFeature(cv::Mat irisCode, cv::Mat maskNorm) +{ + // count points width and height + cv::Mat pointTemp(applicationPoints); + cv::Mat rowTemp; + + std::vector pointRows; + for (int i = 0; i < applicationPoints.rows; i++) { + rowTemp = pointTemp(cv::Rect(0, i, applicationPoints.cols, 1)); + if (cv::sum(rowTemp)[0] > 0) { + pointRows.push_back(i); + } + } + + int width = irisCode.cols; + int height = pointRows.size(); + rowTemp.release(); + pointTemp.release(); + + int n_codes = irisCode.rows / applicationPoints.rows; + + int irisDataLength = (n_codes + 1) * width * height; + uchar * irisData = new uchar[irisDataLength]; + int irisDataIndex = 0; + + uchar* codePixel = new uchar; + + // save iris code 512 * 8 * 6 + for (int n = 0; n < n_codes; n++) { // 6 + for (auto i : pointRows) { // 8 + i = n * maskNorm.rows + i; + for (int j = 0; j < irisCode.cols; j++) { // 512 + codePixel = (uchar*)(irisCode.data + i * irisCode.step + j); + if (*codePixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *codePixel; + } + } + } + } + + // save iris mask 512 * 8 * 1 + uchar * maskPixel; + for (auto i : pointRows) { // 8 + for (int j = 0; j < irisCode.cols; j++) { // 512 + maskPixel = (uchar*)(maskNorm.data + i * maskNorm.step + j); + if (*maskPixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *maskPixel; + } + } + } + + + uchar * irisFeaturePtr = new uchar[irisDataLength / 8 + 5]; + memset(irisFeaturePtr, 0, irisDataLength / 8 + 5); + + // first byte is width; + irisFeaturePtr[0] = (uchar)width; + irisFeaturePtr[1] = (uchar)(width >> 8); + + // second byte is height; + irisFeaturePtr[2] = (uchar)height; + + // third byte is n_codes + irisFeaturePtr[3] = (uchar)n_codes; + + // fourth byte is n_mask(1) + irisFeaturePtr[4] = (uchar)1; + for (int i = 0; i < irisDataLength; i++) { + irisFeaturePtr[5 + i / 8] += irisData[i] << (7 - (i % 8)); + } + + QByteArray feature; + for (int i = 0; i < irisDataLength / 8 + 5; i++) { + feature.append((char) irisFeaturePtr[i]); + } + + delete[] irisData; + delete[] irisFeaturePtr; + return feature; } float CasicIrisRec::matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2) @@ -283,6 +374,67 @@ } +float CasicIrisRec::matchFeatureCode(uchar *feature1, uchar *feature2) +{ + int width = feature1[0] | feature1[1] << 8; // 32 + int height = feature1[2]; // 8 + int nCode = feature1[3]; // 6 +// int nMask = feature1[4]; + + uchar ** irisData1 = reduceIrisCode(feature1); + uchar ** irisMask1 = reduceIrisMask(feature1); + uchar ** irisData2 = reduceIrisCode(feature2); + uchar ** irisMask2 = reduceIrisMask(feature2); + + int shift = 10; + float score = 1.0; + + int minstep = 0 - shift; + int maxstep = shift; + + for (int s = minstep; s <= maxstep; s++) { + int count = 0; + float mean = 0.0; + for (int n = 0; n < nCode; n++) { + for (auto pos : mvApplicationPoints) { + int row = pos.first / mvApplicationPoints[0].first - 1; + int col = (pos.second + s + width) % width; + + if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { + + uchar tmp1 = irisData1[row + height * n][col]; + uchar tmp2 = irisData2[row + height * n][pos.second]; + mean += tmp1 ^ tmp2; + count += 1; + } + } + } + + //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; + mean = mean / count; + score = mean < score ? mean : score; + + } + +// std::cout << "feature score: " << score << std::endl; + + +// for (int i = 0; i < height * nCode; i++) { +// delete irisData1[i]; +// delete irisData2[i]; +// } +// delete irisData1; +// delete irisData2; + +// for (int i = 0; i < height; i++) { +// delete irisMask1[i]; +// delete irisMask2[i]; +// } +// delete irisMask1; +// delete irisMask2; + return score; +} + cv::Mat CasicIrisRec::addBorders(cv::Mat pSrc, int width) { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); @@ -298,4 +450,39 @@ return result; } +uchar ** CasicIrisRec::reduceIrisCode(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2] * feature[3]; + + uchar ** reduceCode = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + reduceCode[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = i * width + j; + reduceCode[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return reduceCode; +} + +uchar ** CasicIrisRec::reduceIrisMask(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2]; // 8 + int nCode = feature[3]; // 6 + + uchar ** irisMask = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + irisMask[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = width * height * nCode + i * width + j; + irisMask[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return irisMask; +} + } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index f6ca8ac..2d9616e 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -5,6 +5,8 @@ #define NORM_HEIGHT 64 #define M_PI 3.1415926535897323846 +#include +#include #include namespace iristrt @@ -15,28 +17,28 @@ public: CasicIrisRec(); - CasicIrisRec(const char * gaborFilterFileName,const char * applicationPointsFileName); - ~CasicIrisRec(); cv::Mat normalize(cv::Mat image, int iris_x, int iris_y, int iris_r,int pupil_x, int pupil_y, int pupil_r); - cv::Mat encodeToImage(cv::Mat normalizedImage); + QByteArray extractFeature(cv::Mat irisCode, cv::Mat maskNorm); float matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2); + float matchFeatureCode(uchar * feature1, uchar * feature2); private: std::vector gaborFilters; - cv::Mat applicationPoints; + std::vector> mvApplicationPoints; std::vector loadGaborFilters(const char * gaborFilterFileName); - cv::Mat loadApplicationPoints(const char * applicationPointsFileName); cv::Mat addBorders(cv::Mat pSrc, int width); + uchar ** reduceIrisCode(uchar * feature); + uchar ** reduceIrisMask(uchar * feature); }; // end of class CasicIrisRec diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 37a0ed6..63eda4d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,3 +1,7 @@ +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + #include "IrisDataDao.h" IrisDataDao::IrisDataDao(QObject *parent) : BaseDao(parent) @@ -37,7 +41,7 @@ result.append(item); } -// LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } @@ -104,7 +108,7 @@ result.insert("right_iris_code3", query.value("right_iris_code3")); } -// LOG_DEBUG(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); + LOG_TRACE(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); return result; } @@ -114,7 +118,12 @@ // 新建查询 QSqlQuery query(ConnectionManager::getInstance()->getConnection()); - qulonglong id = ConnectionManager::getInstance()->generateId(); + qulonglong id; + if (object.contains("id") == true) { + id = object.value("id").toULongLong(); + } else { + id = ConnectionManager::getInstance()->generateId(); + } // INSERT语句 QString sql = QString("INSERT INTO IRIS_DATA (ID, PERSON_ID, ID_CARD_NO, LEFT_IRIS_CODE1, RIGHT_IRIS_CODE1) VALUES (:id, :personId, :idCardNo, :left1, :right1)"); @@ -132,7 +141,7 @@ // 执行插入 bool success = query.exec(); -// LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); + LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); // 结束事务 ConnectionManager::getInstance()->getConnection().commit(); diff --git a/dao/RecognitionRecordsDao.cpp b/dao/RecognitionRecordsDao.cpp index 40db453..d795039 100644 --- a/dao/RecognitionRecordsDao.cpp +++ b/dao/RecognitionRecordsDao.cpp @@ -1,4 +1,4 @@ -#include "RecognitionRecordsDao.h" +#include "RecognitionRecordsDao.h" RecognitionRecordsDao::RecognitionRecordsDao(QObject *parent) : BaseDao(parent) { @@ -58,10 +58,8 @@ query.bindValue(":doorCode", object.value("door_code").toString()); query.bindValue(":inoutType", object.value("inout_type").toString()); -// LOG_DEBUG(sql.toStdString()); - // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES (:id, :logInfo)"); + QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES (:id, :logInfo)"); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/dao/SysDictDao.cpp b/dao/SysDictDao.cpp new file mode 100644 index 0000000..7a2bc8b --- /dev/null +++ b/dao/SysDictDao.cpp @@ -0,0 +1,82 @@ +#include "SysDictDao.h" + + +SysDictDao::SysDictDao(QObject *parent) : BaseDao(parent) +{ + +} + +QVector SysDictDao::findAllRecord() +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT"; + + // 执行查询 + query.exec(sql); + + // 返回结果 + QVector result; + + // 遍历查询结果 + while (query.next()) { + QVariantMap item; + + item.insert("id", query.value("id").toLongLong()); + item.insert("code", query.value("code").toString()); + item.insert("name", query.value("name").toString()); + item.insert("pid", query.value("pid").toString()); + + result.append(item); + } + + return result; +} + +QVariantMap SysDictDao::findRecordById(QString id) +{ + QVariantMap item; + return item; +} + + +QVariantMap SysDictDao::findChildDictByCode(QString code) +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT where PID = (SELECT ID FROM SYS_DICT WHERE CODE = :code)"; + query.prepare(sql); + query.bindValue(":code", code); + + // 执行查询 + query.exec(); + + // 返回结果 + QVariantMap result; + + // 遍历查询结果 + while (query.next()) { + result.insert(query.value("code").toString(), query.value("name").toString()); + } + + return result; +} + +QString SysDictDao::save(QVariantMap object) +{ + return "0"; +} + +bool SysDictDao::edit(QVariantMap newObject, QString id) +{ + return false; +} + +bool SysDictDao::dele(QString id) +{ + return false; +} diff --git a/dao/SysDictDao.h b/dao/SysDictDao.h new file mode 100644 index 0000000..7c73aff --- /dev/null +++ b/dao/SysDictDao.h @@ -0,0 +1,23 @@ +#ifndef SYSDICTDAO_H +#define SYSDICTDAO_H + +#include +#include "BaseDao.h" + +class SysDictDao : public BaseDao +{ + Q_OBJECT +public: + explicit SysDictDao(QObject *parent = nullptr); + + QVector findAllRecord(); + QVariantMap findRecordById(QString id); + + QVariantMap findChildDictByCode(QString code); + + QString save(QVariantMap object); + bool edit(QVariantMap newObject, QString id); + bool dele(QString id); +}; + +#endif // SYSDICTDAO_H diff --git a/dao/SysPersonDao.cpp b/dao/SysPersonDao.cpp index dd9480f..19243b1 100644 --- a/dao/SysPersonDao.cpp +++ b/dao/SysPersonDao.cpp @@ -1,4 +1,4 @@ -#include "SysPersonDao.h" +#include "SysPersonDao.h" SysPersonDao::SysPersonDao(QObject *parent) : BaseDao(parent) @@ -56,10 +56,13 @@ QSqlQuery query(ConnectionManager::getInstance()->getConnection()); // 查询语句 - QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = '%1'").arg(id); + QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = :id"); + + query.prepare(sql); + query.bindValue(":id", id); // 执行查询 - query.exec(sql); + query.exec(); // 返回结果 QVariantMap result; @@ -84,8 +87,9 @@ result.insert("person_code", query.value("person_code").toString()); result.insert("deptname", query.value("fullname").toString()); result.insert("sync_id", query.value("sync_id").toString()); - result.insert("hasFace", query.value("face_valid").toString()); - result.insert("hasIris", query.value("iris_valid").toString()); + result.insert("avatar", query.value("avatar").toString()); +// result.insert("hasFace", query.value("face_valid").toString()); +// result.insert("hasIris", query.value("iris_valid").toString()); } // LOG(TRACE) << QString("根据id查询SYS_PERSON表的记录[id=%1][%2]").arg(id).arg(sql).toStdString(); diff --git a/dao/dao.pri b/dao/dao.pri index 1e04ce4..5f3b7f3 100644 --- a/dao/dao.pri +++ b/dao/dao.pri @@ -4,15 +4,17 @@ HEADERS += $$PWD/RecognitionRecordsDao.h HEADERS += $$PWD/SysPersonDao.h HEADERS += $$PWD/SysDeptDao.h +HEADERS += $$PWD/SysDictDao.h SOURCES += $$PWD/BaseDao.cpp SOURCES += $$PWD/IrisDataDao.cpp SOURCES += $$PWD/RecognitionRecordsDao.cpp SOURCES += $$PWD/SysPersonDao.cpp SOURCES += $$PWD/SysDeptDao.cpp +SOURCES += $$PWD/SysDictDao.cpp HEADERS += $$PWD/util/ConnectionManager.h SOURCES += $$PWD/util/ConnectionManager.cpp -#HEADERS += $$PWD/util/CacheManager.h -#SOURCES += $$PWD/util/CacheManager.cpp +HEADERS += $$PWD/util/CacheManager.h +SOURCES += $$PWD/util/CacheManager.cpp diff --git a/dao/util/CacheManager.cpp b/dao/util/CacheManager.cpp new file mode 100644 index 0000000..e415d93 --- /dev/null +++ b/dao/util/CacheManager.cpp @@ -0,0 +1,12 @@ +#include "CacheManager.h" + +CacheManager::CacheManager() +{ + SysDictDao dictDao; + genderName = dictDao.findChildDictByCode("gender"); +} + +QVariantMap CacheManager::getGenderName() +{ + return genderName; +} diff --git a/dao/util/CacheManager.h b/dao/util/CacheManager.h new file mode 100644 index 0000000..5226744 --- /dev/null +++ b/dao/util/CacheManager.h @@ -0,0 +1,31 @@ +#ifndef CACHEMANAGER_H +#define CACHEMANAGER_H + +#include +#include +#include "dao/SysDeptDao.h" +#include "dao/SysDictDao.h" +#include "dao/SysPersonDao.h" +#include "dao/IrisDataDao.h" + +class CacheManager +{ +public: + ~CacheManager() {}; + CacheManager(const CacheManager&)=delete; + CacheManager& operator=(const CacheManager&)=delete; + + static CacheManager& getInstance() { + static CacheManager instance; + return instance; + } + + QVariantMap getGenderName(); + +private: + CacheManager(); + + QVariantMap genderName; +}; + +#endif // CACHEMANAGER_H diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index 1558461..c528381 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -87,9 +87,6 @@ this->cascade->load(cascadeName); } - QElapsedTimer timer; - timer.start(); - std::vector rect; cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); @@ -111,8 +108,8 @@ // .arg(timer.elapsed()).arg(rect.size()) // .arg(rect.at(0).x).arg(rect.at(0).y) // .arg(rect.at(0).width).arg(rect.at(0).height).toStdString()); - qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]") - .arg(timer.elapsed()).arg(rect.size()) + qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]") + .arg(rect.size()) .arg(rect.at(0).x).arg(rect.at(0).y) .arg(rect.at(0).width).arg(rect.at(0).height); @@ -141,20 +138,18 @@ } // 裁剪眼部图像 - cv::Mat halfSize = irisInfo.matData.clone(); - halfSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, + cv::Mat cutSize = irisInfo.matData.clone(); + cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5, SettingConfig::getInstance().IRIS_WIDTH * cutRatio, SettingConfig::getInstance().IRIS_HEIGHT * cutRatio)); - cv::resize(halfSize, halfSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); - cv::flip(halfSize, halfSize, 1); // 左右翻转 + // 裁剪后放大到 640 * 480 + cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); + cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; -// irisInfo.eyeRect = rect.at(0); - - irisInfo.matData = halfSize; -// irisInfo.data = ImageUtil::MatImageToQImage(halfSize); + irisInfo.matData = cutSize; return irisInfo; } @@ -229,9 +224,18 @@ return irisInfo; } +QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo) +{ + QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm); + return irisFeatureCode; +} + float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo) { -// cv::imshow("info", irisInfo.irisCode); -// cv::waitKey(0); return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm); } + +float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other) +{ + return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data())); +} diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index cbee8fe..26fbedc 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -27,7 +27,9 @@ CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); + QByteArray extractFeature(CasicIrisInfo irisInfo); float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo); + float calculatePairPoints(QByteArray feature, QByteArray other); void setCascadeFile(QString filename); void setMinEyeSize(int minEyeSize); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index c8ffe3e..ad456b4 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -177,6 +177,8 @@ // Get the coordinates file >> i; file >> j; + mvApplicationPoints.push_back(QPair(i, j)); + // Set pixel to "on" if (i < 0 || i > applicationPoints.rows - 1 || j < 0 || j > applicationPoints.cols- 1) { @@ -237,7 +239,96 @@ roi.copyTo(dst); //cv::copyTo(img2, dst, NULL); } - return encodeImage; + cv::Mat image8UC1; + encodeImage.convertTo(image8UC1, CV_8UC1); + return image8UC1; +} + +QByteArray CasicIrisRec::extractFeature(cv::Mat irisCode, cv::Mat maskNorm) +{ + // count points width and height + cv::Mat pointTemp(applicationPoints); + cv::Mat rowTemp; + + std::vector pointRows; + for (int i = 0; i < applicationPoints.rows; i++) { + rowTemp = pointTemp(cv::Rect(0, i, applicationPoints.cols, 1)); + if (cv::sum(rowTemp)[0] > 0) { + pointRows.push_back(i); + } + } + + int width = irisCode.cols; + int height = pointRows.size(); + rowTemp.release(); + pointTemp.release(); + + int n_codes = irisCode.rows / applicationPoints.rows; + + int irisDataLength = (n_codes + 1) * width * height; + uchar * irisData = new uchar[irisDataLength]; + int irisDataIndex = 0; + + uchar* codePixel = new uchar; + + // save iris code 512 * 8 * 6 + for (int n = 0; n < n_codes; n++) { // 6 + for (auto i : pointRows) { // 8 + i = n * maskNorm.rows + i; + for (int j = 0; j < irisCode.cols; j++) { // 512 + codePixel = (uchar*)(irisCode.data + i * irisCode.step + j); + if (*codePixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *codePixel; + } + } + } + } + + // save iris mask 512 * 8 * 1 + uchar * maskPixel; + for (auto i : pointRows) { // 8 + for (int j = 0; j < irisCode.cols; j++) { // 512 + maskPixel = (uchar*)(maskNorm.data + i * maskNorm.step + j); + if (*maskPixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *maskPixel; + } + } + } + + + uchar * irisFeaturePtr = new uchar[irisDataLength / 8 + 5]; + memset(irisFeaturePtr, 0, irisDataLength / 8 + 5); + + // first byte is width; + irisFeaturePtr[0] = (uchar)width; + irisFeaturePtr[1] = (uchar)(width >> 8); + + // second byte is height; + irisFeaturePtr[2] = (uchar)height; + + // third byte is n_codes + irisFeaturePtr[3] = (uchar)n_codes; + + // fourth byte is n_mask(1) + irisFeaturePtr[4] = (uchar)1; + for (int i = 0; i < irisDataLength; i++) { + irisFeaturePtr[5 + i / 8] += irisData[i] << (7 - (i % 8)); + } + + QByteArray feature; + for (int i = 0; i < irisDataLength / 8 + 5; i++) { + feature.append((char) irisFeaturePtr[i]); + } + + delete[] irisData; + delete[] irisFeaturePtr; + return feature; } float CasicIrisRec::matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2) @@ -283,6 +374,67 @@ } +float CasicIrisRec::matchFeatureCode(uchar *feature1, uchar *feature2) +{ + int width = feature1[0] | feature1[1] << 8; // 32 + int height = feature1[2]; // 8 + int nCode = feature1[3]; // 6 +// int nMask = feature1[4]; + + uchar ** irisData1 = reduceIrisCode(feature1); + uchar ** irisMask1 = reduceIrisMask(feature1); + uchar ** irisData2 = reduceIrisCode(feature2); + uchar ** irisMask2 = reduceIrisMask(feature2); + + int shift = 10; + float score = 1.0; + + int minstep = 0 - shift; + int maxstep = shift; + + for (int s = minstep; s <= maxstep; s++) { + int count = 0; + float mean = 0.0; + for (int n = 0; n < nCode; n++) { + for (auto pos : mvApplicationPoints) { + int row = pos.first / mvApplicationPoints[0].first - 1; + int col = (pos.second + s + width) % width; + + if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { + + uchar tmp1 = irisData1[row + height * n][col]; + uchar tmp2 = irisData2[row + height * n][pos.second]; + mean += tmp1 ^ tmp2; + count += 1; + } + } + } + + //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; + mean = mean / count; + score = mean < score ? mean : score; + + } + +// std::cout << "feature score: " << score << std::endl; + + +// for (int i = 0; i < height * nCode; i++) { +// delete irisData1[i]; +// delete irisData2[i]; +// } +// delete irisData1; +// delete irisData2; + +// for (int i = 0; i < height; i++) { +// delete irisMask1[i]; +// delete irisMask2[i]; +// } +// delete irisMask1; +// delete irisMask2; + return score; +} + cv::Mat CasicIrisRec::addBorders(cv::Mat pSrc, int width) { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); @@ -298,4 +450,39 @@ return result; } +uchar ** CasicIrisRec::reduceIrisCode(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2] * feature[3]; + + uchar ** reduceCode = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + reduceCode[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = i * width + j; + reduceCode[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return reduceCode; +} + +uchar ** CasicIrisRec::reduceIrisMask(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2]; // 8 + int nCode = feature[3]; // 6 + + uchar ** irisMask = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + irisMask[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = width * height * nCode + i * width + j; + irisMask[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return irisMask; +} + } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index f6ca8ac..2d9616e 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -5,6 +5,8 @@ #define NORM_HEIGHT 64 #define M_PI 3.1415926535897323846 +#include +#include #include namespace iristrt @@ -15,28 +17,28 @@ public: CasicIrisRec(); - CasicIrisRec(const char * gaborFilterFileName,const char * applicationPointsFileName); - ~CasicIrisRec(); cv::Mat normalize(cv::Mat image, int iris_x, int iris_y, int iris_r,int pupil_x, int pupil_y, int pupil_r); - cv::Mat encodeToImage(cv::Mat normalizedImage); + QByteArray extractFeature(cv::Mat irisCode, cv::Mat maskNorm); float matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2); + float matchFeatureCode(uchar * feature1, uchar * feature2); private: std::vector gaborFilters; - cv::Mat applicationPoints; + std::vector> mvApplicationPoints; std::vector loadGaborFilters(const char * gaborFilterFileName); - cv::Mat loadApplicationPoints(const char * applicationPointsFileName); cv::Mat addBorders(cv::Mat pSrc, int width); + uchar ** reduceIrisCode(uchar * feature); + uchar ** reduceIrisMask(uchar * feature); }; // end of class CasicIrisRec diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 37a0ed6..63eda4d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,3 +1,7 @@ +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + #include "IrisDataDao.h" IrisDataDao::IrisDataDao(QObject *parent) : BaseDao(parent) @@ -37,7 +41,7 @@ result.append(item); } -// LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } @@ -104,7 +108,7 @@ result.insert("right_iris_code3", query.value("right_iris_code3")); } -// LOG_DEBUG(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); + LOG_TRACE(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); return result; } @@ -114,7 +118,12 @@ // 新建查询 QSqlQuery query(ConnectionManager::getInstance()->getConnection()); - qulonglong id = ConnectionManager::getInstance()->generateId(); + qulonglong id; + if (object.contains("id") == true) { + id = object.value("id").toULongLong(); + } else { + id = ConnectionManager::getInstance()->generateId(); + } // INSERT语句 QString sql = QString("INSERT INTO IRIS_DATA (ID, PERSON_ID, ID_CARD_NO, LEFT_IRIS_CODE1, RIGHT_IRIS_CODE1) VALUES (:id, :personId, :idCardNo, :left1, :right1)"); @@ -132,7 +141,7 @@ // 执行插入 bool success = query.exec(); -// LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); + LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); // 结束事务 ConnectionManager::getInstance()->getConnection().commit(); diff --git a/dao/RecognitionRecordsDao.cpp b/dao/RecognitionRecordsDao.cpp index 40db453..d795039 100644 --- a/dao/RecognitionRecordsDao.cpp +++ b/dao/RecognitionRecordsDao.cpp @@ -1,4 +1,4 @@ -#include "RecognitionRecordsDao.h" +#include "RecognitionRecordsDao.h" RecognitionRecordsDao::RecognitionRecordsDao(QObject *parent) : BaseDao(parent) { @@ -58,10 +58,8 @@ query.bindValue(":doorCode", object.value("door_code").toString()); query.bindValue(":inoutType", object.value("inout_type").toString()); -// LOG_DEBUG(sql.toStdString()); - // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES (:id, :logInfo)"); + QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES (:id, :logInfo)"); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/dao/SysDictDao.cpp b/dao/SysDictDao.cpp new file mode 100644 index 0000000..7a2bc8b --- /dev/null +++ b/dao/SysDictDao.cpp @@ -0,0 +1,82 @@ +#include "SysDictDao.h" + + +SysDictDao::SysDictDao(QObject *parent) : BaseDao(parent) +{ + +} + +QVector SysDictDao::findAllRecord() +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT"; + + // 执行查询 + query.exec(sql); + + // 返回结果 + QVector result; + + // 遍历查询结果 + while (query.next()) { + QVariantMap item; + + item.insert("id", query.value("id").toLongLong()); + item.insert("code", query.value("code").toString()); + item.insert("name", query.value("name").toString()); + item.insert("pid", query.value("pid").toString()); + + result.append(item); + } + + return result; +} + +QVariantMap SysDictDao::findRecordById(QString id) +{ + QVariantMap item; + return item; +} + + +QVariantMap SysDictDao::findChildDictByCode(QString code) +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT where PID = (SELECT ID FROM SYS_DICT WHERE CODE = :code)"; + query.prepare(sql); + query.bindValue(":code", code); + + // 执行查询 + query.exec(); + + // 返回结果 + QVariantMap result; + + // 遍历查询结果 + while (query.next()) { + result.insert(query.value("code").toString(), query.value("name").toString()); + } + + return result; +} + +QString SysDictDao::save(QVariantMap object) +{ + return "0"; +} + +bool SysDictDao::edit(QVariantMap newObject, QString id) +{ + return false; +} + +bool SysDictDao::dele(QString id) +{ + return false; +} diff --git a/dao/SysDictDao.h b/dao/SysDictDao.h new file mode 100644 index 0000000..7c73aff --- /dev/null +++ b/dao/SysDictDao.h @@ -0,0 +1,23 @@ +#ifndef SYSDICTDAO_H +#define SYSDICTDAO_H + +#include +#include "BaseDao.h" + +class SysDictDao : public BaseDao +{ + Q_OBJECT +public: + explicit SysDictDao(QObject *parent = nullptr); + + QVector findAllRecord(); + QVariantMap findRecordById(QString id); + + QVariantMap findChildDictByCode(QString code); + + QString save(QVariantMap object); + bool edit(QVariantMap newObject, QString id); + bool dele(QString id); +}; + +#endif // SYSDICTDAO_H diff --git a/dao/SysPersonDao.cpp b/dao/SysPersonDao.cpp index dd9480f..19243b1 100644 --- a/dao/SysPersonDao.cpp +++ b/dao/SysPersonDao.cpp @@ -1,4 +1,4 @@ -#include "SysPersonDao.h" +#include "SysPersonDao.h" SysPersonDao::SysPersonDao(QObject *parent) : BaseDao(parent) @@ -56,10 +56,13 @@ QSqlQuery query(ConnectionManager::getInstance()->getConnection()); // 查询语句 - QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = '%1'").arg(id); + QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = :id"); + + query.prepare(sql); + query.bindValue(":id", id); // 执行查询 - query.exec(sql); + query.exec(); // 返回结果 QVariantMap result; @@ -84,8 +87,9 @@ result.insert("person_code", query.value("person_code").toString()); result.insert("deptname", query.value("fullname").toString()); result.insert("sync_id", query.value("sync_id").toString()); - result.insert("hasFace", query.value("face_valid").toString()); - result.insert("hasIris", query.value("iris_valid").toString()); + result.insert("avatar", query.value("avatar").toString()); +// result.insert("hasFace", query.value("face_valid").toString()); +// result.insert("hasIris", query.value("iris_valid").toString()); } // LOG(TRACE) << QString("根据id查询SYS_PERSON表的记录[id=%1][%2]").arg(id).arg(sql).toStdString(); diff --git a/dao/dao.pri b/dao/dao.pri index 1e04ce4..5f3b7f3 100644 --- a/dao/dao.pri +++ b/dao/dao.pri @@ -4,15 +4,17 @@ HEADERS += $$PWD/RecognitionRecordsDao.h HEADERS += $$PWD/SysPersonDao.h HEADERS += $$PWD/SysDeptDao.h +HEADERS += $$PWD/SysDictDao.h SOURCES += $$PWD/BaseDao.cpp SOURCES += $$PWD/IrisDataDao.cpp SOURCES += $$PWD/RecognitionRecordsDao.cpp SOURCES += $$PWD/SysPersonDao.cpp SOURCES += $$PWD/SysDeptDao.cpp +SOURCES += $$PWD/SysDictDao.cpp HEADERS += $$PWD/util/ConnectionManager.h SOURCES += $$PWD/util/ConnectionManager.cpp -#HEADERS += $$PWD/util/CacheManager.h -#SOURCES += $$PWD/util/CacheManager.cpp +HEADERS += $$PWD/util/CacheManager.h +SOURCES += $$PWD/util/CacheManager.cpp diff --git a/dao/util/CacheManager.cpp b/dao/util/CacheManager.cpp new file mode 100644 index 0000000..e415d93 --- /dev/null +++ b/dao/util/CacheManager.cpp @@ -0,0 +1,12 @@ +#include "CacheManager.h" + +CacheManager::CacheManager() +{ + SysDictDao dictDao; + genderName = dictDao.findChildDictByCode("gender"); +} + +QVariantMap CacheManager::getGenderName() +{ + return genderName; +} diff --git a/dao/util/CacheManager.h b/dao/util/CacheManager.h new file mode 100644 index 0000000..5226744 --- /dev/null +++ b/dao/util/CacheManager.h @@ -0,0 +1,31 @@ +#ifndef CACHEMANAGER_H +#define CACHEMANAGER_H + +#include +#include +#include "dao/SysDeptDao.h" +#include "dao/SysDictDao.h" +#include "dao/SysPersonDao.h" +#include "dao/IrisDataDao.h" + +class CacheManager +{ +public: + ~CacheManager() {}; + CacheManager(const CacheManager&)=delete; + CacheManager& operator=(const CacheManager&)=delete; + + static CacheManager& getInstance() { + static CacheManager instance; + return instance; + } + + QVariantMap getGenderName(); + +private: + CacheManager(); + + QVariantMap genderName; +}; + +#endif // CACHEMANAGER_H diff --git a/dao/util/ConnectionManager.cpp b/dao/util/ConnectionManager.cpp index 84b17be..fed7b8d 100644 --- a/dao/util/ConnectionManager.cpp +++ b/dao/util/ConnectionManager.cpp @@ -1,4 +1,8 @@ -#include "ConnectionManager.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ConnectionManager.h" #include Q_GLOBAL_STATIC(ConnectionManager, cm) @@ -18,10 +22,10 @@ bool succ = conn.open(); if (succ == true) { -// LOG_INFO(QString("打开数据库操作正常[Open Database Success]").toStdString()); + LOG_INFO(QString("打开数据库操作正常[Open Database Success]").toStdString()); } else { -// LOG_ERROR(QString("打开数据库操作失败[Open Database Failed]").toStdString()); + LOG_ERROR(QString("打开数据库操作失败[Open Database Failed]").toStdString()); } } } diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index 1558461..c528381 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -87,9 +87,6 @@ this->cascade->load(cascadeName); } - QElapsedTimer timer; - timer.start(); - std::vector rect; cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); @@ -111,8 +108,8 @@ // .arg(timer.elapsed()).arg(rect.size()) // .arg(rect.at(0).x).arg(rect.at(0).y) // .arg(rect.at(0).width).arg(rect.at(0).height).toStdString()); - qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]") - .arg(timer.elapsed()).arg(rect.size()) + qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]") + .arg(rect.size()) .arg(rect.at(0).x).arg(rect.at(0).y) .arg(rect.at(0).width).arg(rect.at(0).height); @@ -141,20 +138,18 @@ } // 裁剪眼部图像 - cv::Mat halfSize = irisInfo.matData.clone(); - halfSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, + cv::Mat cutSize = irisInfo.matData.clone(); + cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5, SettingConfig::getInstance().IRIS_WIDTH * cutRatio, SettingConfig::getInstance().IRIS_HEIGHT * cutRatio)); - cv::resize(halfSize, halfSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); - cv::flip(halfSize, halfSize, 1); // 左右翻转 + // 裁剪后放大到 640 * 480 + cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); + cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; -// irisInfo.eyeRect = rect.at(0); - - irisInfo.matData = halfSize; -// irisInfo.data = ImageUtil::MatImageToQImage(halfSize); + irisInfo.matData = cutSize; return irisInfo; } @@ -229,9 +224,18 @@ return irisInfo; } +QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo) +{ + QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm); + return irisFeatureCode; +} + float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo) { -// cv::imshow("info", irisInfo.irisCode); -// cv::waitKey(0); return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm); } + +float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other) +{ + return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data())); +} diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index cbee8fe..26fbedc 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -27,7 +27,9 @@ CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); + QByteArray extractFeature(CasicIrisInfo irisInfo); float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo); + float calculatePairPoints(QByteArray feature, QByteArray other); void setCascadeFile(QString filename); void setMinEyeSize(int minEyeSize); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index c8ffe3e..ad456b4 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -177,6 +177,8 @@ // Get the coordinates file >> i; file >> j; + mvApplicationPoints.push_back(QPair(i, j)); + // Set pixel to "on" if (i < 0 || i > applicationPoints.rows - 1 || j < 0 || j > applicationPoints.cols- 1) { @@ -237,7 +239,96 @@ roi.copyTo(dst); //cv::copyTo(img2, dst, NULL); } - return encodeImage; + cv::Mat image8UC1; + encodeImage.convertTo(image8UC1, CV_8UC1); + return image8UC1; +} + +QByteArray CasicIrisRec::extractFeature(cv::Mat irisCode, cv::Mat maskNorm) +{ + // count points width and height + cv::Mat pointTemp(applicationPoints); + cv::Mat rowTemp; + + std::vector pointRows; + for (int i = 0; i < applicationPoints.rows; i++) { + rowTemp = pointTemp(cv::Rect(0, i, applicationPoints.cols, 1)); + if (cv::sum(rowTemp)[0] > 0) { + pointRows.push_back(i); + } + } + + int width = irisCode.cols; + int height = pointRows.size(); + rowTemp.release(); + pointTemp.release(); + + int n_codes = irisCode.rows / applicationPoints.rows; + + int irisDataLength = (n_codes + 1) * width * height; + uchar * irisData = new uchar[irisDataLength]; + int irisDataIndex = 0; + + uchar* codePixel = new uchar; + + // save iris code 512 * 8 * 6 + for (int n = 0; n < n_codes; n++) { // 6 + for (auto i : pointRows) { // 8 + i = n * maskNorm.rows + i; + for (int j = 0; j < irisCode.cols; j++) { // 512 + codePixel = (uchar*)(irisCode.data + i * irisCode.step + j); + if (*codePixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *codePixel; + } + } + } + } + + // save iris mask 512 * 8 * 1 + uchar * maskPixel; + for (auto i : pointRows) { // 8 + for (int j = 0; j < irisCode.cols; j++) { // 512 + maskPixel = (uchar*)(maskNorm.data + i * maskNorm.step + j); + if (*maskPixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *maskPixel; + } + } + } + + + uchar * irisFeaturePtr = new uchar[irisDataLength / 8 + 5]; + memset(irisFeaturePtr, 0, irisDataLength / 8 + 5); + + // first byte is width; + irisFeaturePtr[0] = (uchar)width; + irisFeaturePtr[1] = (uchar)(width >> 8); + + // second byte is height; + irisFeaturePtr[2] = (uchar)height; + + // third byte is n_codes + irisFeaturePtr[3] = (uchar)n_codes; + + // fourth byte is n_mask(1) + irisFeaturePtr[4] = (uchar)1; + for (int i = 0; i < irisDataLength; i++) { + irisFeaturePtr[5 + i / 8] += irisData[i] << (7 - (i % 8)); + } + + QByteArray feature; + for (int i = 0; i < irisDataLength / 8 + 5; i++) { + feature.append((char) irisFeaturePtr[i]); + } + + delete[] irisData; + delete[] irisFeaturePtr; + return feature; } float CasicIrisRec::matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2) @@ -283,6 +374,67 @@ } +float CasicIrisRec::matchFeatureCode(uchar *feature1, uchar *feature2) +{ + int width = feature1[0] | feature1[1] << 8; // 32 + int height = feature1[2]; // 8 + int nCode = feature1[3]; // 6 +// int nMask = feature1[4]; + + uchar ** irisData1 = reduceIrisCode(feature1); + uchar ** irisMask1 = reduceIrisMask(feature1); + uchar ** irisData2 = reduceIrisCode(feature2); + uchar ** irisMask2 = reduceIrisMask(feature2); + + int shift = 10; + float score = 1.0; + + int minstep = 0 - shift; + int maxstep = shift; + + for (int s = minstep; s <= maxstep; s++) { + int count = 0; + float mean = 0.0; + for (int n = 0; n < nCode; n++) { + for (auto pos : mvApplicationPoints) { + int row = pos.first / mvApplicationPoints[0].first - 1; + int col = (pos.second + s + width) % width; + + if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { + + uchar tmp1 = irisData1[row + height * n][col]; + uchar tmp2 = irisData2[row + height * n][pos.second]; + mean += tmp1 ^ tmp2; + count += 1; + } + } + } + + //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; + mean = mean / count; + score = mean < score ? mean : score; + + } + +// std::cout << "feature score: " << score << std::endl; + + +// for (int i = 0; i < height * nCode; i++) { +// delete irisData1[i]; +// delete irisData2[i]; +// } +// delete irisData1; +// delete irisData2; + +// for (int i = 0; i < height; i++) { +// delete irisMask1[i]; +// delete irisMask2[i]; +// } +// delete irisMask1; +// delete irisMask2; + return score; +} + cv::Mat CasicIrisRec::addBorders(cv::Mat pSrc, int width) { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); @@ -298,4 +450,39 @@ return result; } +uchar ** CasicIrisRec::reduceIrisCode(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2] * feature[3]; + + uchar ** reduceCode = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + reduceCode[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = i * width + j; + reduceCode[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return reduceCode; +} + +uchar ** CasicIrisRec::reduceIrisMask(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2]; // 8 + int nCode = feature[3]; // 6 + + uchar ** irisMask = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + irisMask[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = width * height * nCode + i * width + j; + irisMask[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return irisMask; +} + } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index f6ca8ac..2d9616e 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -5,6 +5,8 @@ #define NORM_HEIGHT 64 #define M_PI 3.1415926535897323846 +#include +#include #include namespace iristrt @@ -15,28 +17,28 @@ public: CasicIrisRec(); - CasicIrisRec(const char * gaborFilterFileName,const char * applicationPointsFileName); - ~CasicIrisRec(); cv::Mat normalize(cv::Mat image, int iris_x, int iris_y, int iris_r,int pupil_x, int pupil_y, int pupil_r); - cv::Mat encodeToImage(cv::Mat normalizedImage); + QByteArray extractFeature(cv::Mat irisCode, cv::Mat maskNorm); float matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2); + float matchFeatureCode(uchar * feature1, uchar * feature2); private: std::vector gaborFilters; - cv::Mat applicationPoints; + std::vector> mvApplicationPoints; std::vector loadGaborFilters(const char * gaborFilterFileName); - cv::Mat loadApplicationPoints(const char * applicationPointsFileName); cv::Mat addBorders(cv::Mat pSrc, int width); + uchar ** reduceIrisCode(uchar * feature); + uchar ** reduceIrisMask(uchar * feature); }; // end of class CasicIrisRec diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 37a0ed6..63eda4d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,3 +1,7 @@ +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + #include "IrisDataDao.h" IrisDataDao::IrisDataDao(QObject *parent) : BaseDao(parent) @@ -37,7 +41,7 @@ result.append(item); } -// LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } @@ -104,7 +108,7 @@ result.insert("right_iris_code3", query.value("right_iris_code3")); } -// LOG_DEBUG(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); + LOG_TRACE(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); return result; } @@ -114,7 +118,12 @@ // 新建查询 QSqlQuery query(ConnectionManager::getInstance()->getConnection()); - qulonglong id = ConnectionManager::getInstance()->generateId(); + qulonglong id; + if (object.contains("id") == true) { + id = object.value("id").toULongLong(); + } else { + id = ConnectionManager::getInstance()->generateId(); + } // INSERT语句 QString sql = QString("INSERT INTO IRIS_DATA (ID, PERSON_ID, ID_CARD_NO, LEFT_IRIS_CODE1, RIGHT_IRIS_CODE1) VALUES (:id, :personId, :idCardNo, :left1, :right1)"); @@ -132,7 +141,7 @@ // 执行插入 bool success = query.exec(); -// LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); + LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); // 结束事务 ConnectionManager::getInstance()->getConnection().commit(); diff --git a/dao/RecognitionRecordsDao.cpp b/dao/RecognitionRecordsDao.cpp index 40db453..d795039 100644 --- a/dao/RecognitionRecordsDao.cpp +++ b/dao/RecognitionRecordsDao.cpp @@ -1,4 +1,4 @@ -#include "RecognitionRecordsDao.h" +#include "RecognitionRecordsDao.h" RecognitionRecordsDao::RecognitionRecordsDao(QObject *parent) : BaseDao(parent) { @@ -58,10 +58,8 @@ query.bindValue(":doorCode", object.value("door_code").toString()); query.bindValue(":inoutType", object.value("inout_type").toString()); -// LOG_DEBUG(sql.toStdString()); - // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES (:id, :logInfo)"); + QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES (:id, :logInfo)"); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/dao/SysDictDao.cpp b/dao/SysDictDao.cpp new file mode 100644 index 0000000..7a2bc8b --- /dev/null +++ b/dao/SysDictDao.cpp @@ -0,0 +1,82 @@ +#include "SysDictDao.h" + + +SysDictDao::SysDictDao(QObject *parent) : BaseDao(parent) +{ + +} + +QVector SysDictDao::findAllRecord() +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT"; + + // 执行查询 + query.exec(sql); + + // 返回结果 + QVector result; + + // 遍历查询结果 + while (query.next()) { + QVariantMap item; + + item.insert("id", query.value("id").toLongLong()); + item.insert("code", query.value("code").toString()); + item.insert("name", query.value("name").toString()); + item.insert("pid", query.value("pid").toString()); + + result.append(item); + } + + return result; +} + +QVariantMap SysDictDao::findRecordById(QString id) +{ + QVariantMap item; + return item; +} + + +QVariantMap SysDictDao::findChildDictByCode(QString code) +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT where PID = (SELECT ID FROM SYS_DICT WHERE CODE = :code)"; + query.prepare(sql); + query.bindValue(":code", code); + + // 执行查询 + query.exec(); + + // 返回结果 + QVariantMap result; + + // 遍历查询结果 + while (query.next()) { + result.insert(query.value("code").toString(), query.value("name").toString()); + } + + return result; +} + +QString SysDictDao::save(QVariantMap object) +{ + return "0"; +} + +bool SysDictDao::edit(QVariantMap newObject, QString id) +{ + return false; +} + +bool SysDictDao::dele(QString id) +{ + return false; +} diff --git a/dao/SysDictDao.h b/dao/SysDictDao.h new file mode 100644 index 0000000..7c73aff --- /dev/null +++ b/dao/SysDictDao.h @@ -0,0 +1,23 @@ +#ifndef SYSDICTDAO_H +#define SYSDICTDAO_H + +#include +#include "BaseDao.h" + +class SysDictDao : public BaseDao +{ + Q_OBJECT +public: + explicit SysDictDao(QObject *parent = nullptr); + + QVector findAllRecord(); + QVariantMap findRecordById(QString id); + + QVariantMap findChildDictByCode(QString code); + + QString save(QVariantMap object); + bool edit(QVariantMap newObject, QString id); + bool dele(QString id); +}; + +#endif // SYSDICTDAO_H diff --git a/dao/SysPersonDao.cpp b/dao/SysPersonDao.cpp index dd9480f..19243b1 100644 --- a/dao/SysPersonDao.cpp +++ b/dao/SysPersonDao.cpp @@ -1,4 +1,4 @@ -#include "SysPersonDao.h" +#include "SysPersonDao.h" SysPersonDao::SysPersonDao(QObject *parent) : BaseDao(parent) @@ -56,10 +56,13 @@ QSqlQuery query(ConnectionManager::getInstance()->getConnection()); // 查询语句 - QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = '%1'").arg(id); + QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = :id"); + + query.prepare(sql); + query.bindValue(":id", id); // 执行查询 - query.exec(sql); + query.exec(); // 返回结果 QVariantMap result; @@ -84,8 +87,9 @@ result.insert("person_code", query.value("person_code").toString()); result.insert("deptname", query.value("fullname").toString()); result.insert("sync_id", query.value("sync_id").toString()); - result.insert("hasFace", query.value("face_valid").toString()); - result.insert("hasIris", query.value("iris_valid").toString()); + result.insert("avatar", query.value("avatar").toString()); +// result.insert("hasFace", query.value("face_valid").toString()); +// result.insert("hasIris", query.value("iris_valid").toString()); } // LOG(TRACE) << QString("根据id查询SYS_PERSON表的记录[id=%1][%2]").arg(id).arg(sql).toStdString(); diff --git a/dao/dao.pri b/dao/dao.pri index 1e04ce4..5f3b7f3 100644 --- a/dao/dao.pri +++ b/dao/dao.pri @@ -4,15 +4,17 @@ HEADERS += $$PWD/RecognitionRecordsDao.h HEADERS += $$PWD/SysPersonDao.h HEADERS += $$PWD/SysDeptDao.h +HEADERS += $$PWD/SysDictDao.h SOURCES += $$PWD/BaseDao.cpp SOURCES += $$PWD/IrisDataDao.cpp SOURCES += $$PWD/RecognitionRecordsDao.cpp SOURCES += $$PWD/SysPersonDao.cpp SOURCES += $$PWD/SysDeptDao.cpp +SOURCES += $$PWD/SysDictDao.cpp HEADERS += $$PWD/util/ConnectionManager.h SOURCES += $$PWD/util/ConnectionManager.cpp -#HEADERS += $$PWD/util/CacheManager.h -#SOURCES += $$PWD/util/CacheManager.cpp +HEADERS += $$PWD/util/CacheManager.h +SOURCES += $$PWD/util/CacheManager.cpp diff --git a/dao/util/CacheManager.cpp b/dao/util/CacheManager.cpp new file mode 100644 index 0000000..e415d93 --- /dev/null +++ b/dao/util/CacheManager.cpp @@ -0,0 +1,12 @@ +#include "CacheManager.h" + +CacheManager::CacheManager() +{ + SysDictDao dictDao; + genderName = dictDao.findChildDictByCode("gender"); +} + +QVariantMap CacheManager::getGenderName() +{ + return genderName; +} diff --git a/dao/util/CacheManager.h b/dao/util/CacheManager.h new file mode 100644 index 0000000..5226744 --- /dev/null +++ b/dao/util/CacheManager.h @@ -0,0 +1,31 @@ +#ifndef CACHEMANAGER_H +#define CACHEMANAGER_H + +#include +#include +#include "dao/SysDeptDao.h" +#include "dao/SysDictDao.h" +#include "dao/SysPersonDao.h" +#include "dao/IrisDataDao.h" + +class CacheManager +{ +public: + ~CacheManager() {}; + CacheManager(const CacheManager&)=delete; + CacheManager& operator=(const CacheManager&)=delete; + + static CacheManager& getInstance() { + static CacheManager instance; + return instance; + } + + QVariantMap getGenderName(); + +private: + CacheManager(); + + QVariantMap genderName; +}; + +#endif // CACHEMANAGER_H diff --git a/dao/util/ConnectionManager.cpp b/dao/util/ConnectionManager.cpp index 84b17be..fed7b8d 100644 --- a/dao/util/ConnectionManager.cpp +++ b/dao/util/ConnectionManager.cpp @@ -1,4 +1,8 @@ -#include "ConnectionManager.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ConnectionManager.h" #include Q_GLOBAL_STATIC(ConnectionManager, cm) @@ -18,10 +22,10 @@ bool succ = conn.open(); if (succ == true) { -// LOG_INFO(QString("打开数据库操作正常[Open Database Success]").toStdString()); + LOG_INFO(QString("打开数据库操作正常[Open Database Success]").toStdString()); } else { -// LOG_ERROR(QString("打开数据库操作失败[Open Database Failed]").toStdString()); + LOG_ERROR(QString("打开数据库操作失败[Open Database Failed]").toStdString()); } } } diff --git a/device/iris/CasicIrisRecState.cpp b/device/iris/CasicIrisRecState.cpp index 41105e1..c5e5f13 100644 --- a/device/iris/CasicIrisRecState.cpp +++ b/device/iris/CasicIrisRecState.cpp @@ -25,15 +25,43 @@ QDateTime now = QDateTime::currentDateTime(); this->recoginzeId = now.toString("yyyyMMddHHmmsszzz"); this->timeStamp = now.toMSecsSinceEpoch(); + this->timeStampSucc = 0; + this->tryCount = 0; this->noEyeCount = 0; + this->matchedId = ""; -// LOG(DEBUG) << QString("[CasicIrisRecState][initRecognize] 虹膜识别状态初始化").toStdString(); -// LOG_DEBUG(QString("[CasicIrisRecState][initRecognize] 虹膜识别状态初始化").toStdString()); + this->findEyeTmLast = 0; + this->segmentTmLast = 0; + this->extractTmLast = 0; + this->matchTmLast = 0; + this->recogTimeLast = 0; + + LOG_INFO(QString("[initRecognize][%1] 虹膜识别状态初始化").arg(recoginzeId).toStdString()); qDebug() << QString("[CasicIrisRecState][initRecognize][%1] 虹膜识别状态初始化").arg(recoginzeId); } +void CasicIrisRecState::restRecognize() +{ + this->recoginzeId = ""; + this->timeStamp = 0; + this->timeStampSucc = 0; + + this->tryCount = 0; + this->noEyeCount = 0; + + this->matchedId = ""; + this->score = 0.0f; + this->state = IrisRecStateName::REC_NOT_START; + + this->findEyeTmLast = 0; + this->segmentTmLast = 0; + this->extractTmLast = 0; + this->matchTmLast = 0; + this->recogTimeLast = 0; +} + QString CasicIrisRecState::toString() { return QString(QJsonDocument(toJSON()).toJson(QJsonDocument::Compact)); @@ -47,13 +75,19 @@ obj.insert("recoginzeId", recoginzeId); obj.insert("timestamp", timeStamp); obj.insert("timestampSucc", timeStampSucc); + obj.insert("state", state); + obj.insert("matchedId", matchedId); + obj.insert("score", score); + obj.insert("tryCount", tryCount); obj.insert("noEyeCount", noEyeCount); - obj.insert("recogTimeLast", recogTimeLast); - QJsonObject eyeObj; - eyeObj.insert("hasEye", irisInfo->hasEye); + obj.insert("recogTimeLast", recogTimeLast); + obj.insert("findEyeTmLast", findEyeTmLast); + obj.insert("segmentTmLast", segmentTmLast); + obj.insert("extractTmLast", extractTmLast); + obj.insert("matchTmLast", matchTmLast); return obj; } diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index 1558461..c528381 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -87,9 +87,6 @@ this->cascade->load(cascadeName); } - QElapsedTimer timer; - timer.start(); - std::vector rect; cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); @@ -111,8 +108,8 @@ // .arg(timer.elapsed()).arg(rect.size()) // .arg(rect.at(0).x).arg(rect.at(0).y) // .arg(rect.at(0).width).arg(rect.at(0).height).toStdString()); - qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]") - .arg(timer.elapsed()).arg(rect.size()) + qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]") + .arg(rect.size()) .arg(rect.at(0).x).arg(rect.at(0).y) .arg(rect.at(0).width).arg(rect.at(0).height); @@ -141,20 +138,18 @@ } // 裁剪眼部图像 - cv::Mat halfSize = irisInfo.matData.clone(); - halfSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, + cv::Mat cutSize = irisInfo.matData.clone(); + cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5, SettingConfig::getInstance().IRIS_WIDTH * cutRatio, SettingConfig::getInstance().IRIS_HEIGHT * cutRatio)); - cv::resize(halfSize, halfSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); - cv::flip(halfSize, halfSize, 1); // 左右翻转 + // 裁剪后放大到 640 * 480 + cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); + cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; -// irisInfo.eyeRect = rect.at(0); - - irisInfo.matData = halfSize; -// irisInfo.data = ImageUtil::MatImageToQImage(halfSize); + irisInfo.matData = cutSize; return irisInfo; } @@ -229,9 +224,18 @@ return irisInfo; } +QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo) +{ + QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm); + return irisFeatureCode; +} + float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo) { -// cv::imshow("info", irisInfo.irisCode); -// cv::waitKey(0); return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm); } + +float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other) +{ + return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data())); +} diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index cbee8fe..26fbedc 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -27,7 +27,9 @@ CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); + QByteArray extractFeature(CasicIrisInfo irisInfo); float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo); + float calculatePairPoints(QByteArray feature, QByteArray other); void setCascadeFile(QString filename); void setMinEyeSize(int minEyeSize); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index c8ffe3e..ad456b4 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -177,6 +177,8 @@ // Get the coordinates file >> i; file >> j; + mvApplicationPoints.push_back(QPair(i, j)); + // Set pixel to "on" if (i < 0 || i > applicationPoints.rows - 1 || j < 0 || j > applicationPoints.cols- 1) { @@ -237,7 +239,96 @@ roi.copyTo(dst); //cv::copyTo(img2, dst, NULL); } - return encodeImage; + cv::Mat image8UC1; + encodeImage.convertTo(image8UC1, CV_8UC1); + return image8UC1; +} + +QByteArray CasicIrisRec::extractFeature(cv::Mat irisCode, cv::Mat maskNorm) +{ + // count points width and height + cv::Mat pointTemp(applicationPoints); + cv::Mat rowTemp; + + std::vector pointRows; + for (int i = 0; i < applicationPoints.rows; i++) { + rowTemp = pointTemp(cv::Rect(0, i, applicationPoints.cols, 1)); + if (cv::sum(rowTemp)[0] > 0) { + pointRows.push_back(i); + } + } + + int width = irisCode.cols; + int height = pointRows.size(); + rowTemp.release(); + pointTemp.release(); + + int n_codes = irisCode.rows / applicationPoints.rows; + + int irisDataLength = (n_codes + 1) * width * height; + uchar * irisData = new uchar[irisDataLength]; + int irisDataIndex = 0; + + uchar* codePixel = new uchar; + + // save iris code 512 * 8 * 6 + for (int n = 0; n < n_codes; n++) { // 6 + for (auto i : pointRows) { // 8 + i = n * maskNorm.rows + i; + for (int j = 0; j < irisCode.cols; j++) { // 512 + codePixel = (uchar*)(irisCode.data + i * irisCode.step + j); + if (*codePixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *codePixel; + } + } + } + } + + // save iris mask 512 * 8 * 1 + uchar * maskPixel; + for (auto i : pointRows) { // 8 + for (int j = 0; j < irisCode.cols; j++) { // 512 + maskPixel = (uchar*)(maskNorm.data + i * maskNorm.step + j); + if (*maskPixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *maskPixel; + } + } + } + + + uchar * irisFeaturePtr = new uchar[irisDataLength / 8 + 5]; + memset(irisFeaturePtr, 0, irisDataLength / 8 + 5); + + // first byte is width; + irisFeaturePtr[0] = (uchar)width; + irisFeaturePtr[1] = (uchar)(width >> 8); + + // second byte is height; + irisFeaturePtr[2] = (uchar)height; + + // third byte is n_codes + irisFeaturePtr[3] = (uchar)n_codes; + + // fourth byte is n_mask(1) + irisFeaturePtr[4] = (uchar)1; + for (int i = 0; i < irisDataLength; i++) { + irisFeaturePtr[5 + i / 8] += irisData[i] << (7 - (i % 8)); + } + + QByteArray feature; + for (int i = 0; i < irisDataLength / 8 + 5; i++) { + feature.append((char) irisFeaturePtr[i]); + } + + delete[] irisData; + delete[] irisFeaturePtr; + return feature; } float CasicIrisRec::matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2) @@ -283,6 +374,67 @@ } +float CasicIrisRec::matchFeatureCode(uchar *feature1, uchar *feature2) +{ + int width = feature1[0] | feature1[1] << 8; // 32 + int height = feature1[2]; // 8 + int nCode = feature1[3]; // 6 +// int nMask = feature1[4]; + + uchar ** irisData1 = reduceIrisCode(feature1); + uchar ** irisMask1 = reduceIrisMask(feature1); + uchar ** irisData2 = reduceIrisCode(feature2); + uchar ** irisMask2 = reduceIrisMask(feature2); + + int shift = 10; + float score = 1.0; + + int minstep = 0 - shift; + int maxstep = shift; + + for (int s = minstep; s <= maxstep; s++) { + int count = 0; + float mean = 0.0; + for (int n = 0; n < nCode; n++) { + for (auto pos : mvApplicationPoints) { + int row = pos.first / mvApplicationPoints[0].first - 1; + int col = (pos.second + s + width) % width; + + if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { + + uchar tmp1 = irisData1[row + height * n][col]; + uchar tmp2 = irisData2[row + height * n][pos.second]; + mean += tmp1 ^ tmp2; + count += 1; + } + } + } + + //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; + mean = mean / count; + score = mean < score ? mean : score; + + } + +// std::cout << "feature score: " << score << std::endl; + + +// for (int i = 0; i < height * nCode; i++) { +// delete irisData1[i]; +// delete irisData2[i]; +// } +// delete irisData1; +// delete irisData2; + +// for (int i = 0; i < height; i++) { +// delete irisMask1[i]; +// delete irisMask2[i]; +// } +// delete irisMask1; +// delete irisMask2; + return score; +} + cv::Mat CasicIrisRec::addBorders(cv::Mat pSrc, int width) { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); @@ -298,4 +450,39 @@ return result; } +uchar ** CasicIrisRec::reduceIrisCode(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2] * feature[3]; + + uchar ** reduceCode = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + reduceCode[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = i * width + j; + reduceCode[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return reduceCode; +} + +uchar ** CasicIrisRec::reduceIrisMask(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2]; // 8 + int nCode = feature[3]; // 6 + + uchar ** irisMask = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + irisMask[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = width * height * nCode + i * width + j; + irisMask[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return irisMask; +} + } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index f6ca8ac..2d9616e 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -5,6 +5,8 @@ #define NORM_HEIGHT 64 #define M_PI 3.1415926535897323846 +#include +#include #include namespace iristrt @@ -15,28 +17,28 @@ public: CasicIrisRec(); - CasicIrisRec(const char * gaborFilterFileName,const char * applicationPointsFileName); - ~CasicIrisRec(); cv::Mat normalize(cv::Mat image, int iris_x, int iris_y, int iris_r,int pupil_x, int pupil_y, int pupil_r); - cv::Mat encodeToImage(cv::Mat normalizedImage); + QByteArray extractFeature(cv::Mat irisCode, cv::Mat maskNorm); float matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2); + float matchFeatureCode(uchar * feature1, uchar * feature2); private: std::vector gaborFilters; - cv::Mat applicationPoints; + std::vector> mvApplicationPoints; std::vector loadGaborFilters(const char * gaborFilterFileName); - cv::Mat loadApplicationPoints(const char * applicationPointsFileName); cv::Mat addBorders(cv::Mat pSrc, int width); + uchar ** reduceIrisCode(uchar * feature); + uchar ** reduceIrisMask(uchar * feature); }; // end of class CasicIrisRec diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 37a0ed6..63eda4d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,3 +1,7 @@ +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + #include "IrisDataDao.h" IrisDataDao::IrisDataDao(QObject *parent) : BaseDao(parent) @@ -37,7 +41,7 @@ result.append(item); } -// LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } @@ -104,7 +108,7 @@ result.insert("right_iris_code3", query.value("right_iris_code3")); } -// LOG_DEBUG(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); + LOG_TRACE(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); return result; } @@ -114,7 +118,12 @@ // 新建查询 QSqlQuery query(ConnectionManager::getInstance()->getConnection()); - qulonglong id = ConnectionManager::getInstance()->generateId(); + qulonglong id; + if (object.contains("id") == true) { + id = object.value("id").toULongLong(); + } else { + id = ConnectionManager::getInstance()->generateId(); + } // INSERT语句 QString sql = QString("INSERT INTO IRIS_DATA (ID, PERSON_ID, ID_CARD_NO, LEFT_IRIS_CODE1, RIGHT_IRIS_CODE1) VALUES (:id, :personId, :idCardNo, :left1, :right1)"); @@ -132,7 +141,7 @@ // 执行插入 bool success = query.exec(); -// LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); + LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); // 结束事务 ConnectionManager::getInstance()->getConnection().commit(); diff --git a/dao/RecognitionRecordsDao.cpp b/dao/RecognitionRecordsDao.cpp index 40db453..d795039 100644 --- a/dao/RecognitionRecordsDao.cpp +++ b/dao/RecognitionRecordsDao.cpp @@ -1,4 +1,4 @@ -#include "RecognitionRecordsDao.h" +#include "RecognitionRecordsDao.h" RecognitionRecordsDao::RecognitionRecordsDao(QObject *parent) : BaseDao(parent) { @@ -58,10 +58,8 @@ query.bindValue(":doorCode", object.value("door_code").toString()); query.bindValue(":inoutType", object.value("inout_type").toString()); -// LOG_DEBUG(sql.toStdString()); - // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES (:id, :logInfo)"); + QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES (:id, :logInfo)"); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/dao/SysDictDao.cpp b/dao/SysDictDao.cpp new file mode 100644 index 0000000..7a2bc8b --- /dev/null +++ b/dao/SysDictDao.cpp @@ -0,0 +1,82 @@ +#include "SysDictDao.h" + + +SysDictDao::SysDictDao(QObject *parent) : BaseDao(parent) +{ + +} + +QVector SysDictDao::findAllRecord() +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT"; + + // 执行查询 + query.exec(sql); + + // 返回结果 + QVector result; + + // 遍历查询结果 + while (query.next()) { + QVariantMap item; + + item.insert("id", query.value("id").toLongLong()); + item.insert("code", query.value("code").toString()); + item.insert("name", query.value("name").toString()); + item.insert("pid", query.value("pid").toString()); + + result.append(item); + } + + return result; +} + +QVariantMap SysDictDao::findRecordById(QString id) +{ + QVariantMap item; + return item; +} + + +QVariantMap SysDictDao::findChildDictByCode(QString code) +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT where PID = (SELECT ID FROM SYS_DICT WHERE CODE = :code)"; + query.prepare(sql); + query.bindValue(":code", code); + + // 执行查询 + query.exec(); + + // 返回结果 + QVariantMap result; + + // 遍历查询结果 + while (query.next()) { + result.insert(query.value("code").toString(), query.value("name").toString()); + } + + return result; +} + +QString SysDictDao::save(QVariantMap object) +{ + return "0"; +} + +bool SysDictDao::edit(QVariantMap newObject, QString id) +{ + return false; +} + +bool SysDictDao::dele(QString id) +{ + return false; +} diff --git a/dao/SysDictDao.h b/dao/SysDictDao.h new file mode 100644 index 0000000..7c73aff --- /dev/null +++ b/dao/SysDictDao.h @@ -0,0 +1,23 @@ +#ifndef SYSDICTDAO_H +#define SYSDICTDAO_H + +#include +#include "BaseDao.h" + +class SysDictDao : public BaseDao +{ + Q_OBJECT +public: + explicit SysDictDao(QObject *parent = nullptr); + + QVector findAllRecord(); + QVariantMap findRecordById(QString id); + + QVariantMap findChildDictByCode(QString code); + + QString save(QVariantMap object); + bool edit(QVariantMap newObject, QString id); + bool dele(QString id); +}; + +#endif // SYSDICTDAO_H diff --git a/dao/SysPersonDao.cpp b/dao/SysPersonDao.cpp index dd9480f..19243b1 100644 --- a/dao/SysPersonDao.cpp +++ b/dao/SysPersonDao.cpp @@ -1,4 +1,4 @@ -#include "SysPersonDao.h" +#include "SysPersonDao.h" SysPersonDao::SysPersonDao(QObject *parent) : BaseDao(parent) @@ -56,10 +56,13 @@ QSqlQuery query(ConnectionManager::getInstance()->getConnection()); // 查询语句 - QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = '%1'").arg(id); + QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = :id"); + + query.prepare(sql); + query.bindValue(":id", id); // 执行查询 - query.exec(sql); + query.exec(); // 返回结果 QVariantMap result; @@ -84,8 +87,9 @@ result.insert("person_code", query.value("person_code").toString()); result.insert("deptname", query.value("fullname").toString()); result.insert("sync_id", query.value("sync_id").toString()); - result.insert("hasFace", query.value("face_valid").toString()); - result.insert("hasIris", query.value("iris_valid").toString()); + result.insert("avatar", query.value("avatar").toString()); +// result.insert("hasFace", query.value("face_valid").toString()); +// result.insert("hasIris", query.value("iris_valid").toString()); } // LOG(TRACE) << QString("根据id查询SYS_PERSON表的记录[id=%1][%2]").arg(id).arg(sql).toStdString(); diff --git a/dao/dao.pri b/dao/dao.pri index 1e04ce4..5f3b7f3 100644 --- a/dao/dao.pri +++ b/dao/dao.pri @@ -4,15 +4,17 @@ HEADERS += $$PWD/RecognitionRecordsDao.h HEADERS += $$PWD/SysPersonDao.h HEADERS += $$PWD/SysDeptDao.h +HEADERS += $$PWD/SysDictDao.h SOURCES += $$PWD/BaseDao.cpp SOURCES += $$PWD/IrisDataDao.cpp SOURCES += $$PWD/RecognitionRecordsDao.cpp SOURCES += $$PWD/SysPersonDao.cpp SOURCES += $$PWD/SysDeptDao.cpp +SOURCES += $$PWD/SysDictDao.cpp HEADERS += $$PWD/util/ConnectionManager.h SOURCES += $$PWD/util/ConnectionManager.cpp -#HEADERS += $$PWD/util/CacheManager.h -#SOURCES += $$PWD/util/CacheManager.cpp +HEADERS += $$PWD/util/CacheManager.h +SOURCES += $$PWD/util/CacheManager.cpp diff --git a/dao/util/CacheManager.cpp b/dao/util/CacheManager.cpp new file mode 100644 index 0000000..e415d93 --- /dev/null +++ b/dao/util/CacheManager.cpp @@ -0,0 +1,12 @@ +#include "CacheManager.h" + +CacheManager::CacheManager() +{ + SysDictDao dictDao; + genderName = dictDao.findChildDictByCode("gender"); +} + +QVariantMap CacheManager::getGenderName() +{ + return genderName; +} diff --git a/dao/util/CacheManager.h b/dao/util/CacheManager.h new file mode 100644 index 0000000..5226744 --- /dev/null +++ b/dao/util/CacheManager.h @@ -0,0 +1,31 @@ +#ifndef CACHEMANAGER_H +#define CACHEMANAGER_H + +#include +#include +#include "dao/SysDeptDao.h" +#include "dao/SysDictDao.h" +#include "dao/SysPersonDao.h" +#include "dao/IrisDataDao.h" + +class CacheManager +{ +public: + ~CacheManager() {}; + CacheManager(const CacheManager&)=delete; + CacheManager& operator=(const CacheManager&)=delete; + + static CacheManager& getInstance() { + static CacheManager instance; + return instance; + } + + QVariantMap getGenderName(); + +private: + CacheManager(); + + QVariantMap genderName; +}; + +#endif // CACHEMANAGER_H diff --git a/dao/util/ConnectionManager.cpp b/dao/util/ConnectionManager.cpp index 84b17be..fed7b8d 100644 --- a/dao/util/ConnectionManager.cpp +++ b/dao/util/ConnectionManager.cpp @@ -1,4 +1,8 @@ -#include "ConnectionManager.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ConnectionManager.h" #include Q_GLOBAL_STATIC(ConnectionManager, cm) @@ -18,10 +22,10 @@ bool succ = conn.open(); if (succ == true) { -// LOG_INFO(QString("打开数据库操作正常[Open Database Success]").toStdString()); + LOG_INFO(QString("打开数据库操作正常[Open Database Success]").toStdString()); } else { -// LOG_ERROR(QString("打开数据库操作失败[Open Database Failed]").toStdString()); + LOG_ERROR(QString("打开数据库操作失败[Open Database Failed]").toStdString()); } } } diff --git a/device/iris/CasicIrisRecState.cpp b/device/iris/CasicIrisRecState.cpp index 41105e1..c5e5f13 100644 --- a/device/iris/CasicIrisRecState.cpp +++ b/device/iris/CasicIrisRecState.cpp @@ -25,15 +25,43 @@ QDateTime now = QDateTime::currentDateTime(); this->recoginzeId = now.toString("yyyyMMddHHmmsszzz"); this->timeStamp = now.toMSecsSinceEpoch(); + this->timeStampSucc = 0; + this->tryCount = 0; this->noEyeCount = 0; + this->matchedId = ""; -// LOG(DEBUG) << QString("[CasicIrisRecState][initRecognize] 虹膜识别状态初始化").toStdString(); -// LOG_DEBUG(QString("[CasicIrisRecState][initRecognize] 虹膜识别状态初始化").toStdString()); + this->findEyeTmLast = 0; + this->segmentTmLast = 0; + this->extractTmLast = 0; + this->matchTmLast = 0; + this->recogTimeLast = 0; + + LOG_INFO(QString("[initRecognize][%1] 虹膜识别状态初始化").arg(recoginzeId).toStdString()); qDebug() << QString("[CasicIrisRecState][initRecognize][%1] 虹膜识别状态初始化").arg(recoginzeId); } +void CasicIrisRecState::restRecognize() +{ + this->recoginzeId = ""; + this->timeStamp = 0; + this->timeStampSucc = 0; + + this->tryCount = 0; + this->noEyeCount = 0; + + this->matchedId = ""; + this->score = 0.0f; + this->state = IrisRecStateName::REC_NOT_START; + + this->findEyeTmLast = 0; + this->segmentTmLast = 0; + this->extractTmLast = 0; + this->matchTmLast = 0; + this->recogTimeLast = 0; +} + QString CasicIrisRecState::toString() { return QString(QJsonDocument(toJSON()).toJson(QJsonDocument::Compact)); @@ -47,13 +75,19 @@ obj.insert("recoginzeId", recoginzeId); obj.insert("timestamp", timeStamp); obj.insert("timestampSucc", timeStampSucc); + obj.insert("state", state); + obj.insert("matchedId", matchedId); + obj.insert("score", score); + obj.insert("tryCount", tryCount); obj.insert("noEyeCount", noEyeCount); - obj.insert("recogTimeLast", recogTimeLast); - QJsonObject eyeObj; - eyeObj.insert("hasEye", irisInfo->hasEye); + obj.insert("recogTimeLast", recogTimeLast); + obj.insert("findEyeTmLast", findEyeTmLast); + obj.insert("segmentTmLast", segmentTmLast); + obj.insert("extractTmLast", extractTmLast); + obj.insert("matchTmLast", matchTmLast); return obj; } diff --git a/device/iris/CasicIrisRecState.h b/device/iris/CasicIrisRecState.h index 7506581..e978d58 100644 --- a/device/iris/CasicIrisRecState.h +++ b/device/iris/CasicIrisRecState.h @@ -22,6 +22,7 @@ } void initRecognize(); + void restRecognize(); QString toString(); QJsonObject toJSON(); @@ -29,6 +30,11 @@ qint64 timeStamp = 0; // 识别开始时间戳 qint64 timeStampSucc = 0; // 识别成功时的时间戳 qint64 findEyeTmLast = 0; // 找眼操作耗时 + qint64 segmentTmLast = 0; // 图像分割操作耗时 + qint64 extractTmLast = 0; // 编码操作耗时 + qint64 matchTmLast = 0; // 匹配操作耗时 + + float score = 0.0f; // 匹配评分 CasicIrisInfo * irisInfo; @@ -36,7 +42,7 @@ qint8 tryCount = 0; // 识别尝试次数 qint16 noEyeCount = 0; // 连续没有找到眼睛次数 - float recogTimeLast = 0.0; // 识别成功耗时 + qint16 recogTimeLast = 0.0; // 识别成功耗时ms /** * @brief state @@ -53,8 +59,6 @@ enum IrisRecStateName { REC_NOT_START = 0, // 未开始 - REC_LEFT_FIND_EYE = 1, // 检测左眼, 没找到右眼 - REC_RIGHT_FIND_EYE = 2, // 检测右眼, 没找到左眼 REC_FIND_EYE = 3, // 找到左眼和右眼 REC_FEATURE_EXTRACT = 4, // 特征值提取成功 REC_SEARCH_SUCC = 5, // 虹膜库比对成功 diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index 1558461..c528381 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -87,9 +87,6 @@ this->cascade->load(cascadeName); } - QElapsedTimer timer; - timer.start(); - std::vector rect; cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); @@ -111,8 +108,8 @@ // .arg(timer.elapsed()).arg(rect.size()) // .arg(rect.at(0).x).arg(rect.at(0).y) // .arg(rect.at(0).width).arg(rect.at(0).height).toStdString()); - qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]") - .arg(timer.elapsed()).arg(rect.size()) + qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]") + .arg(rect.size()) .arg(rect.at(0).x).arg(rect.at(0).y) .arg(rect.at(0).width).arg(rect.at(0).height); @@ -141,20 +138,18 @@ } // 裁剪眼部图像 - cv::Mat halfSize = irisInfo.matData.clone(); - halfSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, + cv::Mat cutSize = irisInfo.matData.clone(); + cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5, SettingConfig::getInstance().IRIS_WIDTH * cutRatio, SettingConfig::getInstance().IRIS_HEIGHT * cutRatio)); - cv::resize(halfSize, halfSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); - cv::flip(halfSize, halfSize, 1); // 左右翻转 + // 裁剪后放大到 640 * 480 + cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); + cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; -// irisInfo.eyeRect = rect.at(0); - - irisInfo.matData = halfSize; -// irisInfo.data = ImageUtil::MatImageToQImage(halfSize); + irisInfo.matData = cutSize; return irisInfo; } @@ -229,9 +224,18 @@ return irisInfo; } +QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo) +{ + QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm); + return irisFeatureCode; +} + float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo) { -// cv::imshow("info", irisInfo.irisCode); -// cv::waitKey(0); return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm); } + +float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other) +{ + return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data())); +} diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index cbee8fe..26fbedc 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -27,7 +27,9 @@ CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); + QByteArray extractFeature(CasicIrisInfo irisInfo); float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo); + float calculatePairPoints(QByteArray feature, QByteArray other); void setCascadeFile(QString filename); void setMinEyeSize(int minEyeSize); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index c8ffe3e..ad456b4 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -177,6 +177,8 @@ // Get the coordinates file >> i; file >> j; + mvApplicationPoints.push_back(QPair(i, j)); + // Set pixel to "on" if (i < 0 || i > applicationPoints.rows - 1 || j < 0 || j > applicationPoints.cols- 1) { @@ -237,7 +239,96 @@ roi.copyTo(dst); //cv::copyTo(img2, dst, NULL); } - return encodeImage; + cv::Mat image8UC1; + encodeImage.convertTo(image8UC1, CV_8UC1); + return image8UC1; +} + +QByteArray CasicIrisRec::extractFeature(cv::Mat irisCode, cv::Mat maskNorm) +{ + // count points width and height + cv::Mat pointTemp(applicationPoints); + cv::Mat rowTemp; + + std::vector pointRows; + for (int i = 0; i < applicationPoints.rows; i++) { + rowTemp = pointTemp(cv::Rect(0, i, applicationPoints.cols, 1)); + if (cv::sum(rowTemp)[0] > 0) { + pointRows.push_back(i); + } + } + + int width = irisCode.cols; + int height = pointRows.size(); + rowTemp.release(); + pointTemp.release(); + + int n_codes = irisCode.rows / applicationPoints.rows; + + int irisDataLength = (n_codes + 1) * width * height; + uchar * irisData = new uchar[irisDataLength]; + int irisDataIndex = 0; + + uchar* codePixel = new uchar; + + // save iris code 512 * 8 * 6 + for (int n = 0; n < n_codes; n++) { // 6 + for (auto i : pointRows) { // 8 + i = n * maskNorm.rows + i; + for (int j = 0; j < irisCode.cols; j++) { // 512 + codePixel = (uchar*)(irisCode.data + i * irisCode.step + j); + if (*codePixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *codePixel; + } + } + } + } + + // save iris mask 512 * 8 * 1 + uchar * maskPixel; + for (auto i : pointRows) { // 8 + for (int j = 0; j < irisCode.cols; j++) { // 512 + maskPixel = (uchar*)(maskNorm.data + i * maskNorm.step + j); + if (*maskPixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *maskPixel; + } + } + } + + + uchar * irisFeaturePtr = new uchar[irisDataLength / 8 + 5]; + memset(irisFeaturePtr, 0, irisDataLength / 8 + 5); + + // first byte is width; + irisFeaturePtr[0] = (uchar)width; + irisFeaturePtr[1] = (uchar)(width >> 8); + + // second byte is height; + irisFeaturePtr[2] = (uchar)height; + + // third byte is n_codes + irisFeaturePtr[3] = (uchar)n_codes; + + // fourth byte is n_mask(1) + irisFeaturePtr[4] = (uchar)1; + for (int i = 0; i < irisDataLength; i++) { + irisFeaturePtr[5 + i / 8] += irisData[i] << (7 - (i % 8)); + } + + QByteArray feature; + for (int i = 0; i < irisDataLength / 8 + 5; i++) { + feature.append((char) irisFeaturePtr[i]); + } + + delete[] irisData; + delete[] irisFeaturePtr; + return feature; } float CasicIrisRec::matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2) @@ -283,6 +374,67 @@ } +float CasicIrisRec::matchFeatureCode(uchar *feature1, uchar *feature2) +{ + int width = feature1[0] | feature1[1] << 8; // 32 + int height = feature1[2]; // 8 + int nCode = feature1[3]; // 6 +// int nMask = feature1[4]; + + uchar ** irisData1 = reduceIrisCode(feature1); + uchar ** irisMask1 = reduceIrisMask(feature1); + uchar ** irisData2 = reduceIrisCode(feature2); + uchar ** irisMask2 = reduceIrisMask(feature2); + + int shift = 10; + float score = 1.0; + + int minstep = 0 - shift; + int maxstep = shift; + + for (int s = minstep; s <= maxstep; s++) { + int count = 0; + float mean = 0.0; + for (int n = 0; n < nCode; n++) { + for (auto pos : mvApplicationPoints) { + int row = pos.first / mvApplicationPoints[0].first - 1; + int col = (pos.second + s + width) % width; + + if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { + + uchar tmp1 = irisData1[row + height * n][col]; + uchar tmp2 = irisData2[row + height * n][pos.second]; + mean += tmp1 ^ tmp2; + count += 1; + } + } + } + + //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; + mean = mean / count; + score = mean < score ? mean : score; + + } + +// std::cout << "feature score: " << score << std::endl; + + +// for (int i = 0; i < height * nCode; i++) { +// delete irisData1[i]; +// delete irisData2[i]; +// } +// delete irisData1; +// delete irisData2; + +// for (int i = 0; i < height; i++) { +// delete irisMask1[i]; +// delete irisMask2[i]; +// } +// delete irisMask1; +// delete irisMask2; + return score; +} + cv::Mat CasicIrisRec::addBorders(cv::Mat pSrc, int width) { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); @@ -298,4 +450,39 @@ return result; } +uchar ** CasicIrisRec::reduceIrisCode(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2] * feature[3]; + + uchar ** reduceCode = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + reduceCode[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = i * width + j; + reduceCode[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return reduceCode; +} + +uchar ** CasicIrisRec::reduceIrisMask(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2]; // 8 + int nCode = feature[3]; // 6 + + uchar ** irisMask = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + irisMask[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = width * height * nCode + i * width + j; + irisMask[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return irisMask; +} + } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index f6ca8ac..2d9616e 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -5,6 +5,8 @@ #define NORM_HEIGHT 64 #define M_PI 3.1415926535897323846 +#include +#include #include namespace iristrt @@ -15,28 +17,28 @@ public: CasicIrisRec(); - CasicIrisRec(const char * gaborFilterFileName,const char * applicationPointsFileName); - ~CasicIrisRec(); cv::Mat normalize(cv::Mat image, int iris_x, int iris_y, int iris_r,int pupil_x, int pupil_y, int pupil_r); - cv::Mat encodeToImage(cv::Mat normalizedImage); + QByteArray extractFeature(cv::Mat irisCode, cv::Mat maskNorm); float matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2); + float matchFeatureCode(uchar * feature1, uchar * feature2); private: std::vector gaborFilters; - cv::Mat applicationPoints; + std::vector> mvApplicationPoints; std::vector loadGaborFilters(const char * gaborFilterFileName); - cv::Mat loadApplicationPoints(const char * applicationPointsFileName); cv::Mat addBorders(cv::Mat pSrc, int width); + uchar ** reduceIrisCode(uchar * feature); + uchar ** reduceIrisMask(uchar * feature); }; // end of class CasicIrisRec diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 37a0ed6..63eda4d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,3 +1,7 @@ +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + #include "IrisDataDao.h" IrisDataDao::IrisDataDao(QObject *parent) : BaseDao(parent) @@ -37,7 +41,7 @@ result.append(item); } -// LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } @@ -104,7 +108,7 @@ result.insert("right_iris_code3", query.value("right_iris_code3")); } -// LOG_DEBUG(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); + LOG_TRACE(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); return result; } @@ -114,7 +118,12 @@ // 新建查询 QSqlQuery query(ConnectionManager::getInstance()->getConnection()); - qulonglong id = ConnectionManager::getInstance()->generateId(); + qulonglong id; + if (object.contains("id") == true) { + id = object.value("id").toULongLong(); + } else { + id = ConnectionManager::getInstance()->generateId(); + } // INSERT语句 QString sql = QString("INSERT INTO IRIS_DATA (ID, PERSON_ID, ID_CARD_NO, LEFT_IRIS_CODE1, RIGHT_IRIS_CODE1) VALUES (:id, :personId, :idCardNo, :left1, :right1)"); @@ -132,7 +141,7 @@ // 执行插入 bool success = query.exec(); -// LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); + LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); // 结束事务 ConnectionManager::getInstance()->getConnection().commit(); diff --git a/dao/RecognitionRecordsDao.cpp b/dao/RecognitionRecordsDao.cpp index 40db453..d795039 100644 --- a/dao/RecognitionRecordsDao.cpp +++ b/dao/RecognitionRecordsDao.cpp @@ -1,4 +1,4 @@ -#include "RecognitionRecordsDao.h" +#include "RecognitionRecordsDao.h" RecognitionRecordsDao::RecognitionRecordsDao(QObject *parent) : BaseDao(parent) { @@ -58,10 +58,8 @@ query.bindValue(":doorCode", object.value("door_code").toString()); query.bindValue(":inoutType", object.value("inout_type").toString()); -// LOG_DEBUG(sql.toStdString()); - // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES (:id, :logInfo)"); + QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES (:id, :logInfo)"); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/dao/SysDictDao.cpp b/dao/SysDictDao.cpp new file mode 100644 index 0000000..7a2bc8b --- /dev/null +++ b/dao/SysDictDao.cpp @@ -0,0 +1,82 @@ +#include "SysDictDao.h" + + +SysDictDao::SysDictDao(QObject *parent) : BaseDao(parent) +{ + +} + +QVector SysDictDao::findAllRecord() +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT"; + + // 执行查询 + query.exec(sql); + + // 返回结果 + QVector result; + + // 遍历查询结果 + while (query.next()) { + QVariantMap item; + + item.insert("id", query.value("id").toLongLong()); + item.insert("code", query.value("code").toString()); + item.insert("name", query.value("name").toString()); + item.insert("pid", query.value("pid").toString()); + + result.append(item); + } + + return result; +} + +QVariantMap SysDictDao::findRecordById(QString id) +{ + QVariantMap item; + return item; +} + + +QVariantMap SysDictDao::findChildDictByCode(QString code) +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT where PID = (SELECT ID FROM SYS_DICT WHERE CODE = :code)"; + query.prepare(sql); + query.bindValue(":code", code); + + // 执行查询 + query.exec(); + + // 返回结果 + QVariantMap result; + + // 遍历查询结果 + while (query.next()) { + result.insert(query.value("code").toString(), query.value("name").toString()); + } + + return result; +} + +QString SysDictDao::save(QVariantMap object) +{ + return "0"; +} + +bool SysDictDao::edit(QVariantMap newObject, QString id) +{ + return false; +} + +bool SysDictDao::dele(QString id) +{ + return false; +} diff --git a/dao/SysDictDao.h b/dao/SysDictDao.h new file mode 100644 index 0000000..7c73aff --- /dev/null +++ b/dao/SysDictDao.h @@ -0,0 +1,23 @@ +#ifndef SYSDICTDAO_H +#define SYSDICTDAO_H + +#include +#include "BaseDao.h" + +class SysDictDao : public BaseDao +{ + Q_OBJECT +public: + explicit SysDictDao(QObject *parent = nullptr); + + QVector findAllRecord(); + QVariantMap findRecordById(QString id); + + QVariantMap findChildDictByCode(QString code); + + QString save(QVariantMap object); + bool edit(QVariantMap newObject, QString id); + bool dele(QString id); +}; + +#endif // SYSDICTDAO_H diff --git a/dao/SysPersonDao.cpp b/dao/SysPersonDao.cpp index dd9480f..19243b1 100644 --- a/dao/SysPersonDao.cpp +++ b/dao/SysPersonDao.cpp @@ -1,4 +1,4 @@ -#include "SysPersonDao.h" +#include "SysPersonDao.h" SysPersonDao::SysPersonDao(QObject *parent) : BaseDao(parent) @@ -56,10 +56,13 @@ QSqlQuery query(ConnectionManager::getInstance()->getConnection()); // 查询语句 - QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = '%1'").arg(id); + QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = :id"); + + query.prepare(sql); + query.bindValue(":id", id); // 执行查询 - query.exec(sql); + query.exec(); // 返回结果 QVariantMap result; @@ -84,8 +87,9 @@ result.insert("person_code", query.value("person_code").toString()); result.insert("deptname", query.value("fullname").toString()); result.insert("sync_id", query.value("sync_id").toString()); - result.insert("hasFace", query.value("face_valid").toString()); - result.insert("hasIris", query.value("iris_valid").toString()); + result.insert("avatar", query.value("avatar").toString()); +// result.insert("hasFace", query.value("face_valid").toString()); +// result.insert("hasIris", query.value("iris_valid").toString()); } // LOG(TRACE) << QString("根据id查询SYS_PERSON表的记录[id=%1][%2]").arg(id).arg(sql).toStdString(); diff --git a/dao/dao.pri b/dao/dao.pri index 1e04ce4..5f3b7f3 100644 --- a/dao/dao.pri +++ b/dao/dao.pri @@ -4,15 +4,17 @@ HEADERS += $$PWD/RecognitionRecordsDao.h HEADERS += $$PWD/SysPersonDao.h HEADERS += $$PWD/SysDeptDao.h +HEADERS += $$PWD/SysDictDao.h SOURCES += $$PWD/BaseDao.cpp SOURCES += $$PWD/IrisDataDao.cpp SOURCES += $$PWD/RecognitionRecordsDao.cpp SOURCES += $$PWD/SysPersonDao.cpp SOURCES += $$PWD/SysDeptDao.cpp +SOURCES += $$PWD/SysDictDao.cpp HEADERS += $$PWD/util/ConnectionManager.h SOURCES += $$PWD/util/ConnectionManager.cpp -#HEADERS += $$PWD/util/CacheManager.h -#SOURCES += $$PWD/util/CacheManager.cpp +HEADERS += $$PWD/util/CacheManager.h +SOURCES += $$PWD/util/CacheManager.cpp diff --git a/dao/util/CacheManager.cpp b/dao/util/CacheManager.cpp new file mode 100644 index 0000000..e415d93 --- /dev/null +++ b/dao/util/CacheManager.cpp @@ -0,0 +1,12 @@ +#include "CacheManager.h" + +CacheManager::CacheManager() +{ + SysDictDao dictDao; + genderName = dictDao.findChildDictByCode("gender"); +} + +QVariantMap CacheManager::getGenderName() +{ + return genderName; +} diff --git a/dao/util/CacheManager.h b/dao/util/CacheManager.h new file mode 100644 index 0000000..5226744 --- /dev/null +++ b/dao/util/CacheManager.h @@ -0,0 +1,31 @@ +#ifndef CACHEMANAGER_H +#define CACHEMANAGER_H + +#include +#include +#include "dao/SysDeptDao.h" +#include "dao/SysDictDao.h" +#include "dao/SysPersonDao.h" +#include "dao/IrisDataDao.h" + +class CacheManager +{ +public: + ~CacheManager() {}; + CacheManager(const CacheManager&)=delete; + CacheManager& operator=(const CacheManager&)=delete; + + static CacheManager& getInstance() { + static CacheManager instance; + return instance; + } + + QVariantMap getGenderName(); + +private: + CacheManager(); + + QVariantMap genderName; +}; + +#endif // CACHEMANAGER_H diff --git a/dao/util/ConnectionManager.cpp b/dao/util/ConnectionManager.cpp index 84b17be..fed7b8d 100644 --- a/dao/util/ConnectionManager.cpp +++ b/dao/util/ConnectionManager.cpp @@ -1,4 +1,8 @@ -#include "ConnectionManager.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ConnectionManager.h" #include Q_GLOBAL_STATIC(ConnectionManager, cm) @@ -18,10 +22,10 @@ bool succ = conn.open(); if (succ == true) { -// LOG_INFO(QString("打开数据库操作正常[Open Database Success]").toStdString()); + LOG_INFO(QString("打开数据库操作正常[Open Database Success]").toStdString()); } else { -// LOG_ERROR(QString("打开数据库操作失败[Open Database Failed]").toStdString()); + LOG_ERROR(QString("打开数据库操作失败[Open Database Failed]").toStdString()); } } } diff --git a/device/iris/CasicIrisRecState.cpp b/device/iris/CasicIrisRecState.cpp index 41105e1..c5e5f13 100644 --- a/device/iris/CasicIrisRecState.cpp +++ b/device/iris/CasicIrisRecState.cpp @@ -25,15 +25,43 @@ QDateTime now = QDateTime::currentDateTime(); this->recoginzeId = now.toString("yyyyMMddHHmmsszzz"); this->timeStamp = now.toMSecsSinceEpoch(); + this->timeStampSucc = 0; + this->tryCount = 0; this->noEyeCount = 0; + this->matchedId = ""; -// LOG(DEBUG) << QString("[CasicIrisRecState][initRecognize] 虹膜识别状态初始化").toStdString(); -// LOG_DEBUG(QString("[CasicIrisRecState][initRecognize] 虹膜识别状态初始化").toStdString()); + this->findEyeTmLast = 0; + this->segmentTmLast = 0; + this->extractTmLast = 0; + this->matchTmLast = 0; + this->recogTimeLast = 0; + + LOG_INFO(QString("[initRecognize][%1] 虹膜识别状态初始化").arg(recoginzeId).toStdString()); qDebug() << QString("[CasicIrisRecState][initRecognize][%1] 虹膜识别状态初始化").arg(recoginzeId); } +void CasicIrisRecState::restRecognize() +{ + this->recoginzeId = ""; + this->timeStamp = 0; + this->timeStampSucc = 0; + + this->tryCount = 0; + this->noEyeCount = 0; + + this->matchedId = ""; + this->score = 0.0f; + this->state = IrisRecStateName::REC_NOT_START; + + this->findEyeTmLast = 0; + this->segmentTmLast = 0; + this->extractTmLast = 0; + this->matchTmLast = 0; + this->recogTimeLast = 0; +} + QString CasicIrisRecState::toString() { return QString(QJsonDocument(toJSON()).toJson(QJsonDocument::Compact)); @@ -47,13 +75,19 @@ obj.insert("recoginzeId", recoginzeId); obj.insert("timestamp", timeStamp); obj.insert("timestampSucc", timeStampSucc); + obj.insert("state", state); + obj.insert("matchedId", matchedId); + obj.insert("score", score); + obj.insert("tryCount", tryCount); obj.insert("noEyeCount", noEyeCount); - obj.insert("recogTimeLast", recogTimeLast); - QJsonObject eyeObj; - eyeObj.insert("hasEye", irisInfo->hasEye); + obj.insert("recogTimeLast", recogTimeLast); + obj.insert("findEyeTmLast", findEyeTmLast); + obj.insert("segmentTmLast", segmentTmLast); + obj.insert("extractTmLast", extractTmLast); + obj.insert("matchTmLast", matchTmLast); return obj; } diff --git a/device/iris/CasicIrisRecState.h b/device/iris/CasicIrisRecState.h index 7506581..e978d58 100644 --- a/device/iris/CasicIrisRecState.h +++ b/device/iris/CasicIrisRecState.h @@ -22,6 +22,7 @@ } void initRecognize(); + void restRecognize(); QString toString(); QJsonObject toJSON(); @@ -29,6 +30,11 @@ qint64 timeStamp = 0; // 识别开始时间戳 qint64 timeStampSucc = 0; // 识别成功时的时间戳 qint64 findEyeTmLast = 0; // 找眼操作耗时 + qint64 segmentTmLast = 0; // 图像分割操作耗时 + qint64 extractTmLast = 0; // 编码操作耗时 + qint64 matchTmLast = 0; // 匹配操作耗时 + + float score = 0.0f; // 匹配评分 CasicIrisInfo * irisInfo; @@ -36,7 +42,7 @@ qint8 tryCount = 0; // 识别尝试次数 qint16 noEyeCount = 0; // 连续没有找到眼睛次数 - float recogTimeLast = 0.0; // 识别成功耗时 + qint16 recogTimeLast = 0.0; // 识别成功耗时ms /** * @brief state @@ -53,8 +59,6 @@ enum IrisRecStateName { REC_NOT_START = 0, // 未开始 - REC_LEFT_FIND_EYE = 1, // 检测左眼, 没找到右眼 - REC_RIGHT_FIND_EYE = 2, // 检测右眼, 没找到左眼 REC_FIND_EYE = 3, // 找到左眼和右眼 REC_FEATURE_EXTRACT = 4, // 特征值提取成功 REC_SEARCH_SUCC = 5, // 虹膜库比对成功 diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 5ca377e..38f54fe 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -62,10 +62,20 @@ // 3. 取出虹膜图像栈中的一条数据 CasicIrisInfo irisInfo = ProMemory::getInstance().popCasicIris(); - // 4. 调用找眼分类器算法 + QElapsedTimer timer; + timer.start(); + + // 4. 调用找眼分类器算法 第一阶段 casic::iris::CasicIrisInterface::getInstance().setMinEyeSize(SettingConfig::getInstance().MIN_EYE_SIZE); irisInfo = casic::iris::CasicIrisInterface::getInstance().findAndCutEye(irisInfo); + // 找眼计时 + int findEyeLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); + +// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.hasEye = true; + // 4.1 没有找到眼睛则返回 if (irisInfo.hasEye == false) { @@ -77,13 +87,13 @@ continue; } - // 4.2 找到眼睛则开始识别 + // 5. 找到眼睛则开始识别 // 发送信号更新界面 emit startIdentifyIris(); // 调用远程算法进行编码 - if (CasicIrisRecState::getInstance().recoginzeId == "0") + if (CasicIrisRecState::getInstance().recoginzeId == "0" || CasicIrisRecState::getInstance().recoginzeId == "") { // 第一次找到眼则 虹膜识别状态初始化 CasicIrisRecState::getInstance().initRecognize(); @@ -92,10 +102,14 @@ CasicIrisRecState::getInstance().noEyeCount = 0; // 持续未找到眼的次数清零 CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FIND_EYE; - QElapsedTimer timer; - timer.start(); + LOG_DEBUG(QString("[IrisRecogProcess step.1] 找眼及裁剪成功[%1 ms]").arg(findEyeLast).toStdString()); + CasicIrisRecState::getInstance().findEyeTmLast = findEyeLast; + CasicIrisRecState::getInstance().recogTimeLast += findEyeLast; - // 进行预处理 转换成 320 * 240 的三通道图像 送去压缩 + // 6. 分割图像 + timer.restart(); + + // 进行预处理 转换成 320 * 240 的三通道图像 送去分割 cv::Mat segMat; // 图像转换为RGB的彩色图像 @@ -108,7 +122,8 @@ // cv::imwrite(filename, segMat); // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - QByteArray data((char*)segMat.data, SettingConfig::getInstance().IRIS_WIDTH * 0.5 * SettingConfig::getInstance().IRIS_HEIGHT * 0.5 * 3); + int segMatSize = segMat.cols * segMat.rows; + QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 // 发送TCP消息去匹配 emit sendDataToExract(data); @@ -131,27 +146,27 @@ char recvMask[320 * 240 * 1]; char recvIris[320 * 240 * 1]; memset(recvPupil, 0, sizeof(recvPupil)); - memset(recvMask, 0, sizeof(recvMask)); - memset(recvIris, 0, sizeof(recvIris)); + memset(recvMask, 0, sizeof (recvMask)); + memset(recvIris, 0, sizeof (recvIris)); for (int i = 0; i < clientUtil->getResponse().size(); i++) { - if (i < 320 * 240) + if (i < segMatSize) recvPupil[i] = clientUtil->getResponse().at(i); - else if (i >= 320 * 240 && i < 2 * 320 * 240) - recvMask[i - 320 * 240] = clientUtil->getResponse().at(i); + else if (i >= segMatSize && i < 2 * segMatSize) + recvMask[i - segMatSize] = clientUtil->getResponse().at(i); else - recvIris[i - 2 * 320 * 240] = clientUtil->getResponse().at(i); + recvIris[i - 2 * segMatSize] = clientUtil->getResponse().at(i); } - // 成功接收后清除缓存区 - clientUtil->resetRecvBuffer(); - - cv::Mat pupil(240, 320, CV_8UC1, recvPupil); - cv::Mat mask(240, 320, CV_8UC1, recvMask); - cv::Mat iris(240, 320, CV_8UC1, recvIris); + cv::Mat pupil(segMat.rows, segMat.cols, CV_8UC1, recvPupil); + cv::Mat mask(segMat.rows, segMat.cols, CV_8UC1, recvMask); + cv::Mat iris(segMat.rows, segMat.cols, CV_8UC1, recvIris); irisInfo.segResult.innerMask = pupil; irisInfo.segResult.irisMask = mask; irisInfo.segResult.outerCircle = iris; - /* + + // 成功接收后清除缓存区 + 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(); @@ -159,9 +174,15 @@ cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); */ - qDebug() << QString("算法分割图像成功[%1 ms]").arg(timer.elapsed()); + // 第二阶段 分割图像计时 + int segLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 算法分割图像成功[%1 ms]").arg(segLast); + LOG_DEBUG(QString("[IrisRecogProcess step.2] 算法分割图像成功[%1 ms]").arg(segLast).toStdString()); + CasicIrisRecState::getInstance().segmentTmLast = segLast; + CasicIrisRecState::getInstance().recogTimeLast += segLast; - // 分割后的后处理 + // 7. 分割后的后处理 编码及提取特征值 + timer.restart(); if (cv::countNonZero(mask) == 0 || cv::countNonZero(pupil) == 0|| cv::countNonZero(iris) == 0) { qDebug() << "算法分割图像失败,暂停200ms"; @@ -173,38 +194,53 @@ // 状态修改为特征提取 CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; - - timer.restart(); 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")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); +/* + 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(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); +*/ - qDebug() << QString("虹膜图像编码成功[%1 ms]").arg(timer.elapsed()); + // 从编码中提取特征值 + irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); + + int encodeLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 虹膜图像编码并提取特征值成功[%1 ms]").arg(encodeLast); + LOG_DEBUG(QString("[IrisRecogProcess step.3] 虹膜图像编码并提取特征值成功[%1 ms]").arg(encodeLast).toStdString()); + CasicIrisRecState::getInstance().extractTmLast = encodeLast; + CasicIrisRecState::getInstance().recogTimeLast += encodeLast; // 开始匹配 + timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) { CasicIrisFeature feature = ProMemory::getInstance().getIrisFeatures().at(i); - float score = casic::iris::CasicIrisInterface::getInstance().calculateMatchScore(feature, irisInfo); - // SpeakerUtil::getInstance().speak(QString::number(score)); - cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).arg(score).toStdString(), irisInfo.matData); + + 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); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; + CasicIrisRecState::getInstance().score = score; + CasicIrisRecState::getInstance().timeStampSucc = QDateTime::currentMSecsSinceEpoch(); + break ; } } + int matchLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 虹膜库匹配[%1 ms][%2]").arg(matchLast).arg(CasicIrisRecState::getInstance().state); + LOG_DEBUG(QString("[IrisRecogProcess step.4] 虹膜库匹配[%1 ms][%2]").arg(matchLast).arg(CasicIrisRecState::getInstance().state).toStdString()); + CasicIrisRecState::getInstance().matchTmLast = matchLast; + CasicIrisRecState::getInstance().recogTimeLast += matchLast; + if (CasicIrisRecState::getInstance().state == CasicIrisRecState::REC_SEARCH_SUCC) { // 找到匹配结果 - emit findMatchedIris(CasicIrisRecState::getInstance().matchedId); + afterRecogAction(); - ProMemory::getInstance().irisCam->stopCapture(); - ProMemory::getInstance().clearIrisQueue(); - this->setWorking(false); + emit findMatchedIris(CasicIrisRecState::getInstance().matchedId); } else { // 没有匹配上 addOneTryCount(); @@ -215,7 +251,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - + ProMemory::getInstance().irisCam->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index 1558461..c528381 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -87,9 +87,6 @@ this->cascade->load(cascadeName); } - QElapsedTimer timer; - timer.start(); - std::vector rect; cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); @@ -111,8 +108,8 @@ // .arg(timer.elapsed()).arg(rect.size()) // .arg(rect.at(0).x).arg(rect.at(0).y) // .arg(rect.at(0).width).arg(rect.at(0).height).toStdString()); - qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]") - .arg(timer.elapsed()).arg(rect.size()) + qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]") + .arg(rect.size()) .arg(rect.at(0).x).arg(rect.at(0).y) .arg(rect.at(0).width).arg(rect.at(0).height); @@ -141,20 +138,18 @@ } // 裁剪眼部图像 - cv::Mat halfSize = irisInfo.matData.clone(); - halfSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, + cv::Mat cutSize = irisInfo.matData.clone(); + cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5, SettingConfig::getInstance().IRIS_WIDTH * cutRatio, SettingConfig::getInstance().IRIS_HEIGHT * cutRatio)); - cv::resize(halfSize, halfSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); - cv::flip(halfSize, halfSize, 1); // 左右翻转 + // 裁剪后放大到 640 * 480 + cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); + cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; -// irisInfo.eyeRect = rect.at(0); - - irisInfo.matData = halfSize; -// irisInfo.data = ImageUtil::MatImageToQImage(halfSize); + irisInfo.matData = cutSize; return irisInfo; } @@ -229,9 +224,18 @@ return irisInfo; } +QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo) +{ + QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm); + return irisFeatureCode; +} + float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo) { -// cv::imshow("info", irisInfo.irisCode); -// cv::waitKey(0); return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm); } + +float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other) +{ + return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data())); +} diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index cbee8fe..26fbedc 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -27,7 +27,9 @@ CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); + QByteArray extractFeature(CasicIrisInfo irisInfo); float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo); + float calculatePairPoints(QByteArray feature, QByteArray other); void setCascadeFile(QString filename); void setMinEyeSize(int minEyeSize); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index c8ffe3e..ad456b4 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -177,6 +177,8 @@ // Get the coordinates file >> i; file >> j; + mvApplicationPoints.push_back(QPair(i, j)); + // Set pixel to "on" if (i < 0 || i > applicationPoints.rows - 1 || j < 0 || j > applicationPoints.cols- 1) { @@ -237,7 +239,96 @@ roi.copyTo(dst); //cv::copyTo(img2, dst, NULL); } - return encodeImage; + cv::Mat image8UC1; + encodeImage.convertTo(image8UC1, CV_8UC1); + return image8UC1; +} + +QByteArray CasicIrisRec::extractFeature(cv::Mat irisCode, cv::Mat maskNorm) +{ + // count points width and height + cv::Mat pointTemp(applicationPoints); + cv::Mat rowTemp; + + std::vector pointRows; + for (int i = 0; i < applicationPoints.rows; i++) { + rowTemp = pointTemp(cv::Rect(0, i, applicationPoints.cols, 1)); + if (cv::sum(rowTemp)[0] > 0) { + pointRows.push_back(i); + } + } + + int width = irisCode.cols; + int height = pointRows.size(); + rowTemp.release(); + pointTemp.release(); + + int n_codes = irisCode.rows / applicationPoints.rows; + + int irisDataLength = (n_codes + 1) * width * height; + uchar * irisData = new uchar[irisDataLength]; + int irisDataIndex = 0; + + uchar* codePixel = new uchar; + + // save iris code 512 * 8 * 6 + for (int n = 0; n < n_codes; n++) { // 6 + for (auto i : pointRows) { // 8 + i = n * maskNorm.rows + i; + for (int j = 0; j < irisCode.cols; j++) { // 512 + codePixel = (uchar*)(irisCode.data + i * irisCode.step + j); + if (*codePixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *codePixel; + } + } + } + } + + // save iris mask 512 * 8 * 1 + uchar * maskPixel; + for (auto i : pointRows) { // 8 + for (int j = 0; j < irisCode.cols; j++) { // 512 + maskPixel = (uchar*)(maskNorm.data + i * maskNorm.step + j); + if (*maskPixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *maskPixel; + } + } + } + + + uchar * irisFeaturePtr = new uchar[irisDataLength / 8 + 5]; + memset(irisFeaturePtr, 0, irisDataLength / 8 + 5); + + // first byte is width; + irisFeaturePtr[0] = (uchar)width; + irisFeaturePtr[1] = (uchar)(width >> 8); + + // second byte is height; + irisFeaturePtr[2] = (uchar)height; + + // third byte is n_codes + irisFeaturePtr[3] = (uchar)n_codes; + + // fourth byte is n_mask(1) + irisFeaturePtr[4] = (uchar)1; + for (int i = 0; i < irisDataLength; i++) { + irisFeaturePtr[5 + i / 8] += irisData[i] << (7 - (i % 8)); + } + + QByteArray feature; + for (int i = 0; i < irisDataLength / 8 + 5; i++) { + feature.append((char) irisFeaturePtr[i]); + } + + delete[] irisData; + delete[] irisFeaturePtr; + return feature; } float CasicIrisRec::matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2) @@ -283,6 +374,67 @@ } +float CasicIrisRec::matchFeatureCode(uchar *feature1, uchar *feature2) +{ + int width = feature1[0] | feature1[1] << 8; // 32 + int height = feature1[2]; // 8 + int nCode = feature1[3]; // 6 +// int nMask = feature1[4]; + + uchar ** irisData1 = reduceIrisCode(feature1); + uchar ** irisMask1 = reduceIrisMask(feature1); + uchar ** irisData2 = reduceIrisCode(feature2); + uchar ** irisMask2 = reduceIrisMask(feature2); + + int shift = 10; + float score = 1.0; + + int minstep = 0 - shift; + int maxstep = shift; + + for (int s = minstep; s <= maxstep; s++) { + int count = 0; + float mean = 0.0; + for (int n = 0; n < nCode; n++) { + for (auto pos : mvApplicationPoints) { + int row = pos.first / mvApplicationPoints[0].first - 1; + int col = (pos.second + s + width) % width; + + if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { + + uchar tmp1 = irisData1[row + height * n][col]; + uchar tmp2 = irisData2[row + height * n][pos.second]; + mean += tmp1 ^ tmp2; + count += 1; + } + } + } + + //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; + mean = mean / count; + score = mean < score ? mean : score; + + } + +// std::cout << "feature score: " << score << std::endl; + + +// for (int i = 0; i < height * nCode; i++) { +// delete irisData1[i]; +// delete irisData2[i]; +// } +// delete irisData1; +// delete irisData2; + +// for (int i = 0; i < height; i++) { +// delete irisMask1[i]; +// delete irisMask2[i]; +// } +// delete irisMask1; +// delete irisMask2; + return score; +} + cv::Mat CasicIrisRec::addBorders(cv::Mat pSrc, int width) { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); @@ -298,4 +450,39 @@ return result; } +uchar ** CasicIrisRec::reduceIrisCode(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2] * feature[3]; + + uchar ** reduceCode = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + reduceCode[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = i * width + j; + reduceCode[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return reduceCode; +} + +uchar ** CasicIrisRec::reduceIrisMask(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2]; // 8 + int nCode = feature[3]; // 6 + + uchar ** irisMask = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + irisMask[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = width * height * nCode + i * width + j; + irisMask[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return irisMask; +} + } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index f6ca8ac..2d9616e 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -5,6 +5,8 @@ #define NORM_HEIGHT 64 #define M_PI 3.1415926535897323846 +#include +#include #include namespace iristrt @@ -15,28 +17,28 @@ public: CasicIrisRec(); - CasicIrisRec(const char * gaborFilterFileName,const char * applicationPointsFileName); - ~CasicIrisRec(); cv::Mat normalize(cv::Mat image, int iris_x, int iris_y, int iris_r,int pupil_x, int pupil_y, int pupil_r); - cv::Mat encodeToImage(cv::Mat normalizedImage); + QByteArray extractFeature(cv::Mat irisCode, cv::Mat maskNorm); float matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2); + float matchFeatureCode(uchar * feature1, uchar * feature2); private: std::vector gaborFilters; - cv::Mat applicationPoints; + std::vector> mvApplicationPoints; std::vector loadGaborFilters(const char * gaborFilterFileName); - cv::Mat loadApplicationPoints(const char * applicationPointsFileName); cv::Mat addBorders(cv::Mat pSrc, int width); + uchar ** reduceIrisCode(uchar * feature); + uchar ** reduceIrisMask(uchar * feature); }; // end of class CasicIrisRec diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 37a0ed6..63eda4d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,3 +1,7 @@ +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + #include "IrisDataDao.h" IrisDataDao::IrisDataDao(QObject *parent) : BaseDao(parent) @@ -37,7 +41,7 @@ result.append(item); } -// LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } @@ -104,7 +108,7 @@ result.insert("right_iris_code3", query.value("right_iris_code3")); } -// LOG_DEBUG(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); + LOG_TRACE(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); return result; } @@ -114,7 +118,12 @@ // 新建查询 QSqlQuery query(ConnectionManager::getInstance()->getConnection()); - qulonglong id = ConnectionManager::getInstance()->generateId(); + qulonglong id; + if (object.contains("id") == true) { + id = object.value("id").toULongLong(); + } else { + id = ConnectionManager::getInstance()->generateId(); + } // INSERT语句 QString sql = QString("INSERT INTO IRIS_DATA (ID, PERSON_ID, ID_CARD_NO, LEFT_IRIS_CODE1, RIGHT_IRIS_CODE1) VALUES (:id, :personId, :idCardNo, :left1, :right1)"); @@ -132,7 +141,7 @@ // 执行插入 bool success = query.exec(); -// LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); + LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); // 结束事务 ConnectionManager::getInstance()->getConnection().commit(); diff --git a/dao/RecognitionRecordsDao.cpp b/dao/RecognitionRecordsDao.cpp index 40db453..d795039 100644 --- a/dao/RecognitionRecordsDao.cpp +++ b/dao/RecognitionRecordsDao.cpp @@ -1,4 +1,4 @@ -#include "RecognitionRecordsDao.h" +#include "RecognitionRecordsDao.h" RecognitionRecordsDao::RecognitionRecordsDao(QObject *parent) : BaseDao(parent) { @@ -58,10 +58,8 @@ query.bindValue(":doorCode", object.value("door_code").toString()); query.bindValue(":inoutType", object.value("inout_type").toString()); -// LOG_DEBUG(sql.toStdString()); - // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES (:id, :logInfo)"); + QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES (:id, :logInfo)"); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/dao/SysDictDao.cpp b/dao/SysDictDao.cpp new file mode 100644 index 0000000..7a2bc8b --- /dev/null +++ b/dao/SysDictDao.cpp @@ -0,0 +1,82 @@ +#include "SysDictDao.h" + + +SysDictDao::SysDictDao(QObject *parent) : BaseDao(parent) +{ + +} + +QVector SysDictDao::findAllRecord() +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT"; + + // 执行查询 + query.exec(sql); + + // 返回结果 + QVector result; + + // 遍历查询结果 + while (query.next()) { + QVariantMap item; + + item.insert("id", query.value("id").toLongLong()); + item.insert("code", query.value("code").toString()); + item.insert("name", query.value("name").toString()); + item.insert("pid", query.value("pid").toString()); + + result.append(item); + } + + return result; +} + +QVariantMap SysDictDao::findRecordById(QString id) +{ + QVariantMap item; + return item; +} + + +QVariantMap SysDictDao::findChildDictByCode(QString code) +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT where PID = (SELECT ID FROM SYS_DICT WHERE CODE = :code)"; + query.prepare(sql); + query.bindValue(":code", code); + + // 执行查询 + query.exec(); + + // 返回结果 + QVariantMap result; + + // 遍历查询结果 + while (query.next()) { + result.insert(query.value("code").toString(), query.value("name").toString()); + } + + return result; +} + +QString SysDictDao::save(QVariantMap object) +{ + return "0"; +} + +bool SysDictDao::edit(QVariantMap newObject, QString id) +{ + return false; +} + +bool SysDictDao::dele(QString id) +{ + return false; +} diff --git a/dao/SysDictDao.h b/dao/SysDictDao.h new file mode 100644 index 0000000..7c73aff --- /dev/null +++ b/dao/SysDictDao.h @@ -0,0 +1,23 @@ +#ifndef SYSDICTDAO_H +#define SYSDICTDAO_H + +#include +#include "BaseDao.h" + +class SysDictDao : public BaseDao +{ + Q_OBJECT +public: + explicit SysDictDao(QObject *parent = nullptr); + + QVector findAllRecord(); + QVariantMap findRecordById(QString id); + + QVariantMap findChildDictByCode(QString code); + + QString save(QVariantMap object); + bool edit(QVariantMap newObject, QString id); + bool dele(QString id); +}; + +#endif // SYSDICTDAO_H diff --git a/dao/SysPersonDao.cpp b/dao/SysPersonDao.cpp index dd9480f..19243b1 100644 --- a/dao/SysPersonDao.cpp +++ b/dao/SysPersonDao.cpp @@ -1,4 +1,4 @@ -#include "SysPersonDao.h" +#include "SysPersonDao.h" SysPersonDao::SysPersonDao(QObject *parent) : BaseDao(parent) @@ -56,10 +56,13 @@ QSqlQuery query(ConnectionManager::getInstance()->getConnection()); // 查询语句 - QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = '%1'").arg(id); + QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = :id"); + + query.prepare(sql); + query.bindValue(":id", id); // 执行查询 - query.exec(sql); + query.exec(); // 返回结果 QVariantMap result; @@ -84,8 +87,9 @@ result.insert("person_code", query.value("person_code").toString()); result.insert("deptname", query.value("fullname").toString()); result.insert("sync_id", query.value("sync_id").toString()); - result.insert("hasFace", query.value("face_valid").toString()); - result.insert("hasIris", query.value("iris_valid").toString()); + result.insert("avatar", query.value("avatar").toString()); +// result.insert("hasFace", query.value("face_valid").toString()); +// result.insert("hasIris", query.value("iris_valid").toString()); } // LOG(TRACE) << QString("根据id查询SYS_PERSON表的记录[id=%1][%2]").arg(id).arg(sql).toStdString(); diff --git a/dao/dao.pri b/dao/dao.pri index 1e04ce4..5f3b7f3 100644 --- a/dao/dao.pri +++ b/dao/dao.pri @@ -4,15 +4,17 @@ HEADERS += $$PWD/RecognitionRecordsDao.h HEADERS += $$PWD/SysPersonDao.h HEADERS += $$PWD/SysDeptDao.h +HEADERS += $$PWD/SysDictDao.h SOURCES += $$PWD/BaseDao.cpp SOURCES += $$PWD/IrisDataDao.cpp SOURCES += $$PWD/RecognitionRecordsDao.cpp SOURCES += $$PWD/SysPersonDao.cpp SOURCES += $$PWD/SysDeptDao.cpp +SOURCES += $$PWD/SysDictDao.cpp HEADERS += $$PWD/util/ConnectionManager.h SOURCES += $$PWD/util/ConnectionManager.cpp -#HEADERS += $$PWD/util/CacheManager.h -#SOURCES += $$PWD/util/CacheManager.cpp +HEADERS += $$PWD/util/CacheManager.h +SOURCES += $$PWD/util/CacheManager.cpp diff --git a/dao/util/CacheManager.cpp b/dao/util/CacheManager.cpp new file mode 100644 index 0000000..e415d93 --- /dev/null +++ b/dao/util/CacheManager.cpp @@ -0,0 +1,12 @@ +#include "CacheManager.h" + +CacheManager::CacheManager() +{ + SysDictDao dictDao; + genderName = dictDao.findChildDictByCode("gender"); +} + +QVariantMap CacheManager::getGenderName() +{ + return genderName; +} diff --git a/dao/util/CacheManager.h b/dao/util/CacheManager.h new file mode 100644 index 0000000..5226744 --- /dev/null +++ b/dao/util/CacheManager.h @@ -0,0 +1,31 @@ +#ifndef CACHEMANAGER_H +#define CACHEMANAGER_H + +#include +#include +#include "dao/SysDeptDao.h" +#include "dao/SysDictDao.h" +#include "dao/SysPersonDao.h" +#include "dao/IrisDataDao.h" + +class CacheManager +{ +public: + ~CacheManager() {}; + CacheManager(const CacheManager&)=delete; + CacheManager& operator=(const CacheManager&)=delete; + + static CacheManager& getInstance() { + static CacheManager instance; + return instance; + } + + QVariantMap getGenderName(); + +private: + CacheManager(); + + QVariantMap genderName; +}; + +#endif // CACHEMANAGER_H diff --git a/dao/util/ConnectionManager.cpp b/dao/util/ConnectionManager.cpp index 84b17be..fed7b8d 100644 --- a/dao/util/ConnectionManager.cpp +++ b/dao/util/ConnectionManager.cpp @@ -1,4 +1,8 @@ -#include "ConnectionManager.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ConnectionManager.h" #include Q_GLOBAL_STATIC(ConnectionManager, cm) @@ -18,10 +22,10 @@ bool succ = conn.open(); if (succ == true) { -// LOG_INFO(QString("打开数据库操作正常[Open Database Success]").toStdString()); + LOG_INFO(QString("打开数据库操作正常[Open Database Success]").toStdString()); } else { -// LOG_ERROR(QString("打开数据库操作失败[Open Database Failed]").toStdString()); + LOG_ERROR(QString("打开数据库操作失败[Open Database Failed]").toStdString()); } } } diff --git a/device/iris/CasicIrisRecState.cpp b/device/iris/CasicIrisRecState.cpp index 41105e1..c5e5f13 100644 --- a/device/iris/CasicIrisRecState.cpp +++ b/device/iris/CasicIrisRecState.cpp @@ -25,15 +25,43 @@ QDateTime now = QDateTime::currentDateTime(); this->recoginzeId = now.toString("yyyyMMddHHmmsszzz"); this->timeStamp = now.toMSecsSinceEpoch(); + this->timeStampSucc = 0; + this->tryCount = 0; this->noEyeCount = 0; + this->matchedId = ""; -// LOG(DEBUG) << QString("[CasicIrisRecState][initRecognize] 虹膜识别状态初始化").toStdString(); -// LOG_DEBUG(QString("[CasicIrisRecState][initRecognize] 虹膜识别状态初始化").toStdString()); + this->findEyeTmLast = 0; + this->segmentTmLast = 0; + this->extractTmLast = 0; + this->matchTmLast = 0; + this->recogTimeLast = 0; + + LOG_INFO(QString("[initRecognize][%1] 虹膜识别状态初始化").arg(recoginzeId).toStdString()); qDebug() << QString("[CasicIrisRecState][initRecognize][%1] 虹膜识别状态初始化").arg(recoginzeId); } +void CasicIrisRecState::restRecognize() +{ + this->recoginzeId = ""; + this->timeStamp = 0; + this->timeStampSucc = 0; + + this->tryCount = 0; + this->noEyeCount = 0; + + this->matchedId = ""; + this->score = 0.0f; + this->state = IrisRecStateName::REC_NOT_START; + + this->findEyeTmLast = 0; + this->segmentTmLast = 0; + this->extractTmLast = 0; + this->matchTmLast = 0; + this->recogTimeLast = 0; +} + QString CasicIrisRecState::toString() { return QString(QJsonDocument(toJSON()).toJson(QJsonDocument::Compact)); @@ -47,13 +75,19 @@ obj.insert("recoginzeId", recoginzeId); obj.insert("timestamp", timeStamp); obj.insert("timestampSucc", timeStampSucc); + obj.insert("state", state); + obj.insert("matchedId", matchedId); + obj.insert("score", score); + obj.insert("tryCount", tryCount); obj.insert("noEyeCount", noEyeCount); - obj.insert("recogTimeLast", recogTimeLast); - QJsonObject eyeObj; - eyeObj.insert("hasEye", irisInfo->hasEye); + obj.insert("recogTimeLast", recogTimeLast); + obj.insert("findEyeTmLast", findEyeTmLast); + obj.insert("segmentTmLast", segmentTmLast); + obj.insert("extractTmLast", extractTmLast); + obj.insert("matchTmLast", matchTmLast); return obj; } diff --git a/device/iris/CasicIrisRecState.h b/device/iris/CasicIrisRecState.h index 7506581..e978d58 100644 --- a/device/iris/CasicIrisRecState.h +++ b/device/iris/CasicIrisRecState.h @@ -22,6 +22,7 @@ } void initRecognize(); + void restRecognize(); QString toString(); QJsonObject toJSON(); @@ -29,6 +30,11 @@ qint64 timeStamp = 0; // 识别开始时间戳 qint64 timeStampSucc = 0; // 识别成功时的时间戳 qint64 findEyeTmLast = 0; // 找眼操作耗时 + qint64 segmentTmLast = 0; // 图像分割操作耗时 + qint64 extractTmLast = 0; // 编码操作耗时 + qint64 matchTmLast = 0; // 匹配操作耗时 + + float score = 0.0f; // 匹配评分 CasicIrisInfo * irisInfo; @@ -36,7 +42,7 @@ qint8 tryCount = 0; // 识别尝试次数 qint16 noEyeCount = 0; // 连续没有找到眼睛次数 - float recogTimeLast = 0.0; // 识别成功耗时 + qint16 recogTimeLast = 0.0; // 识别成功耗时ms /** * @brief state @@ -53,8 +59,6 @@ enum IrisRecStateName { REC_NOT_START = 0, // 未开始 - REC_LEFT_FIND_EYE = 1, // 检测左眼, 没找到右眼 - REC_RIGHT_FIND_EYE = 2, // 检测右眼, 没找到左眼 REC_FIND_EYE = 3, // 找到左眼和右眼 REC_FEATURE_EXTRACT = 4, // 特征值提取成功 REC_SEARCH_SUCC = 5, // 虹膜库比对成功 diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 5ca377e..38f54fe 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -62,10 +62,20 @@ // 3. 取出虹膜图像栈中的一条数据 CasicIrisInfo irisInfo = ProMemory::getInstance().popCasicIris(); - // 4. 调用找眼分类器算法 + QElapsedTimer timer; + timer.start(); + + // 4. 调用找眼分类器算法 第一阶段 casic::iris::CasicIrisInterface::getInstance().setMinEyeSize(SettingConfig::getInstance().MIN_EYE_SIZE); irisInfo = casic::iris::CasicIrisInterface::getInstance().findAndCutEye(irisInfo); + // 找眼计时 + int findEyeLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); + +// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.hasEye = true; + // 4.1 没有找到眼睛则返回 if (irisInfo.hasEye == false) { @@ -77,13 +87,13 @@ continue; } - // 4.2 找到眼睛则开始识别 + // 5. 找到眼睛则开始识别 // 发送信号更新界面 emit startIdentifyIris(); // 调用远程算法进行编码 - if (CasicIrisRecState::getInstance().recoginzeId == "0") + if (CasicIrisRecState::getInstance().recoginzeId == "0" || CasicIrisRecState::getInstance().recoginzeId == "") { // 第一次找到眼则 虹膜识别状态初始化 CasicIrisRecState::getInstance().initRecognize(); @@ -92,10 +102,14 @@ CasicIrisRecState::getInstance().noEyeCount = 0; // 持续未找到眼的次数清零 CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FIND_EYE; - QElapsedTimer timer; - timer.start(); + LOG_DEBUG(QString("[IrisRecogProcess step.1] 找眼及裁剪成功[%1 ms]").arg(findEyeLast).toStdString()); + CasicIrisRecState::getInstance().findEyeTmLast = findEyeLast; + CasicIrisRecState::getInstance().recogTimeLast += findEyeLast; - // 进行预处理 转换成 320 * 240 的三通道图像 送去压缩 + // 6. 分割图像 + timer.restart(); + + // 进行预处理 转换成 320 * 240 的三通道图像 送去分割 cv::Mat segMat; // 图像转换为RGB的彩色图像 @@ -108,7 +122,8 @@ // cv::imwrite(filename, segMat); // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - QByteArray data((char*)segMat.data, SettingConfig::getInstance().IRIS_WIDTH * 0.5 * SettingConfig::getInstance().IRIS_HEIGHT * 0.5 * 3); + int segMatSize = segMat.cols * segMat.rows; + QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 // 发送TCP消息去匹配 emit sendDataToExract(data); @@ -131,27 +146,27 @@ char recvMask[320 * 240 * 1]; char recvIris[320 * 240 * 1]; memset(recvPupil, 0, sizeof(recvPupil)); - memset(recvMask, 0, sizeof(recvMask)); - memset(recvIris, 0, sizeof(recvIris)); + memset(recvMask, 0, sizeof (recvMask)); + memset(recvIris, 0, sizeof (recvIris)); for (int i = 0; i < clientUtil->getResponse().size(); i++) { - if (i < 320 * 240) + if (i < segMatSize) recvPupil[i] = clientUtil->getResponse().at(i); - else if (i >= 320 * 240 && i < 2 * 320 * 240) - recvMask[i - 320 * 240] = clientUtil->getResponse().at(i); + else if (i >= segMatSize && i < 2 * segMatSize) + recvMask[i - segMatSize] = clientUtil->getResponse().at(i); else - recvIris[i - 2 * 320 * 240] = clientUtil->getResponse().at(i); + recvIris[i - 2 * segMatSize] = clientUtil->getResponse().at(i); } - // 成功接收后清除缓存区 - clientUtil->resetRecvBuffer(); - - cv::Mat pupil(240, 320, CV_8UC1, recvPupil); - cv::Mat mask(240, 320, CV_8UC1, recvMask); - cv::Mat iris(240, 320, CV_8UC1, recvIris); + cv::Mat pupil(segMat.rows, segMat.cols, CV_8UC1, recvPupil); + cv::Mat mask(segMat.rows, segMat.cols, CV_8UC1, recvMask); + cv::Mat iris(segMat.rows, segMat.cols, CV_8UC1, recvIris); irisInfo.segResult.innerMask = pupil; irisInfo.segResult.irisMask = mask; irisInfo.segResult.outerCircle = iris; - /* + + // 成功接收后清除缓存区 + 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(); @@ -159,9 +174,15 @@ cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); */ - qDebug() << QString("算法分割图像成功[%1 ms]").arg(timer.elapsed()); + // 第二阶段 分割图像计时 + int segLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 算法分割图像成功[%1 ms]").arg(segLast); + LOG_DEBUG(QString("[IrisRecogProcess step.2] 算法分割图像成功[%1 ms]").arg(segLast).toStdString()); + CasicIrisRecState::getInstance().segmentTmLast = segLast; + CasicIrisRecState::getInstance().recogTimeLast += segLast; - // 分割后的后处理 + // 7. 分割后的后处理 编码及提取特征值 + timer.restart(); if (cv::countNonZero(mask) == 0 || cv::countNonZero(pupil) == 0|| cv::countNonZero(iris) == 0) { qDebug() << "算法分割图像失败,暂停200ms"; @@ -173,38 +194,53 @@ // 状态修改为特征提取 CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; - - timer.restart(); 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")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); +/* + 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(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); +*/ - qDebug() << QString("虹膜图像编码成功[%1 ms]").arg(timer.elapsed()); + // 从编码中提取特征值 + irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); + + int encodeLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 虹膜图像编码并提取特征值成功[%1 ms]").arg(encodeLast); + LOG_DEBUG(QString("[IrisRecogProcess step.3] 虹膜图像编码并提取特征值成功[%1 ms]").arg(encodeLast).toStdString()); + CasicIrisRecState::getInstance().extractTmLast = encodeLast; + CasicIrisRecState::getInstance().recogTimeLast += encodeLast; // 开始匹配 + timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) { CasicIrisFeature feature = ProMemory::getInstance().getIrisFeatures().at(i); - float score = casic::iris::CasicIrisInterface::getInstance().calculateMatchScore(feature, irisInfo); - // SpeakerUtil::getInstance().speak(QString::number(score)); - cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).arg(score).toStdString(), irisInfo.matData); + + 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); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; + CasicIrisRecState::getInstance().score = score; + CasicIrisRecState::getInstance().timeStampSucc = QDateTime::currentMSecsSinceEpoch(); + break ; } } + int matchLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 虹膜库匹配[%1 ms][%2]").arg(matchLast).arg(CasicIrisRecState::getInstance().state); + LOG_DEBUG(QString("[IrisRecogProcess step.4] 虹膜库匹配[%1 ms][%2]").arg(matchLast).arg(CasicIrisRecState::getInstance().state).toStdString()); + CasicIrisRecState::getInstance().matchTmLast = matchLast; + CasicIrisRecState::getInstance().recogTimeLast += matchLast; + if (CasicIrisRecState::getInstance().state == CasicIrisRecState::REC_SEARCH_SUCC) { // 找到匹配结果 - emit findMatchedIris(CasicIrisRecState::getInstance().matchedId); + afterRecogAction(); - ProMemory::getInstance().irisCam->stopCapture(); - ProMemory::getInstance().clearIrisQueue(); - this->setWorking(false); + emit findMatchedIris(CasicIrisRecState::getInstance().matchedId); } else { // 没有匹配上 addOneTryCount(); @@ -215,7 +251,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - + ProMemory::getInstance().irisCam->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } diff --git a/utils/LogUtil.h b/utils/LogUtil.h new file mode 100644 index 0000000..eb4147c --- /dev/null +++ b/utils/LogUtil.h @@ -0,0 +1,87 @@ +#ifndef LOGUTIL_H +#define LOGUTIL_H + +#include "spdlog/spdlog.h" +#include "spdlog/sinks/daily_file_sink.h" + +#include "SettingConfig.h" + +// use embedded macro to support file and line number +#define LOG_TRACE(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::trace, __VA_ARGS__) +#define LOG_DEBUG(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::debug, __VA_ARGS__) +#define LOG_INFO(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::info, __VA_ARGS__) +#define LOG_WARN(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::warn, __VA_ARGS__) +#define LOG_ERROR(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::err, __VA_ARGS__) + + +class LogUtil +{ +public: + ~LogUtil() + { + spdlog::drop_all(); + } + + LogUtil(const LogUtil&)=delete; + LogUtil& operator=(const LogUtil&)=delete; //禁止生成默认赋值函数 + + // magic singleton static + static LogUtil* getInstance() { + static LogUtil instance; + return &instance; + } + + std::shared_ptr getLogger() + { + return m_logger; + } + +private: + LogUtil() + { + try { + + // Create a daily logger - a new file is created every day on 00:00am + m_logger = spdlog::daily_logger_mt("CasicIrisIdentify", SettingConfig::getInstance().LOG_FILE.toStdString(), 0, 0); + + m_logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e][%l] %v"); + + std::string level = SettingConfig::getInstance().LOG_LEVEL.toStdString(); + if (level == "trace") + { + m_logger->set_level(spdlog::level::trace); + m_logger->flush_on(spdlog::level::trace); + } + else if (level == "debug") + { + m_logger->set_level(spdlog::level::debug); + m_logger->flush_on(spdlog::level::debug); + } + else if (level == "info") + { + m_logger->set_level(spdlog::level::info); + m_logger->flush_on(spdlog::level::info); + } + else if (level == "warn") + { + m_logger->set_level(spdlog::level::warn); + m_logger->flush_on(spdlog::level::warn); + } + else if (level == "error") + { + m_logger->set_level(spdlog::level::err); + m_logger->flush_on(spdlog::level::err); + } + } + catch (const spdlog::spdlog_ex& ex) + { + spdlog::error("init log failed: {}",ex.what()); + + } + } + + std::shared_ptr m_logger; + +}; + +#endif // LOGUTIL_H diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index 1558461..c528381 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -87,9 +87,6 @@ this->cascade->load(cascadeName); } - QElapsedTimer timer; - timer.start(); - std::vector rect; cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); @@ -111,8 +108,8 @@ // .arg(timer.elapsed()).arg(rect.size()) // .arg(rect.at(0).x).arg(rect.at(0).y) // .arg(rect.at(0).width).arg(rect.at(0).height).toStdString()); - qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]") - .arg(timer.elapsed()).arg(rect.size()) + qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]") + .arg(rect.size()) .arg(rect.at(0).x).arg(rect.at(0).y) .arg(rect.at(0).width).arg(rect.at(0).height); @@ -141,20 +138,18 @@ } // 裁剪眼部图像 - cv::Mat halfSize = irisInfo.matData.clone(); - halfSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, + cv::Mat cutSize = irisInfo.matData.clone(); + cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5, SettingConfig::getInstance().IRIS_WIDTH * cutRatio, SettingConfig::getInstance().IRIS_HEIGHT * cutRatio)); - cv::resize(halfSize, halfSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); - cv::flip(halfSize, halfSize, 1); // 左右翻转 + // 裁剪后放大到 640 * 480 + cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); + cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; -// irisInfo.eyeRect = rect.at(0); - - irisInfo.matData = halfSize; -// irisInfo.data = ImageUtil::MatImageToQImage(halfSize); + irisInfo.matData = cutSize; return irisInfo; } @@ -229,9 +224,18 @@ return irisInfo; } +QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo) +{ + QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm); + return irisFeatureCode; +} + float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo) { -// cv::imshow("info", irisInfo.irisCode); -// cv::waitKey(0); return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm); } + +float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other) +{ + return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data())); +} diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index cbee8fe..26fbedc 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -27,7 +27,9 @@ CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); + QByteArray extractFeature(CasicIrisInfo irisInfo); float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo); + float calculatePairPoints(QByteArray feature, QByteArray other); void setCascadeFile(QString filename); void setMinEyeSize(int minEyeSize); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index c8ffe3e..ad456b4 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -177,6 +177,8 @@ // Get the coordinates file >> i; file >> j; + mvApplicationPoints.push_back(QPair(i, j)); + // Set pixel to "on" if (i < 0 || i > applicationPoints.rows - 1 || j < 0 || j > applicationPoints.cols- 1) { @@ -237,7 +239,96 @@ roi.copyTo(dst); //cv::copyTo(img2, dst, NULL); } - return encodeImage; + cv::Mat image8UC1; + encodeImage.convertTo(image8UC1, CV_8UC1); + return image8UC1; +} + +QByteArray CasicIrisRec::extractFeature(cv::Mat irisCode, cv::Mat maskNorm) +{ + // count points width and height + cv::Mat pointTemp(applicationPoints); + cv::Mat rowTemp; + + std::vector pointRows; + for (int i = 0; i < applicationPoints.rows; i++) { + rowTemp = pointTemp(cv::Rect(0, i, applicationPoints.cols, 1)); + if (cv::sum(rowTemp)[0] > 0) { + pointRows.push_back(i); + } + } + + int width = irisCode.cols; + int height = pointRows.size(); + rowTemp.release(); + pointTemp.release(); + + int n_codes = irisCode.rows / applicationPoints.rows; + + int irisDataLength = (n_codes + 1) * width * height; + uchar * irisData = new uchar[irisDataLength]; + int irisDataIndex = 0; + + uchar* codePixel = new uchar; + + // save iris code 512 * 8 * 6 + for (int n = 0; n < n_codes; n++) { // 6 + for (auto i : pointRows) { // 8 + i = n * maskNorm.rows + i; + for (int j = 0; j < irisCode.cols; j++) { // 512 + codePixel = (uchar*)(irisCode.data + i * irisCode.step + j); + if (*codePixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *codePixel; + } + } + } + } + + // save iris mask 512 * 8 * 1 + uchar * maskPixel; + for (auto i : pointRows) { // 8 + for (int j = 0; j < irisCode.cols; j++) { // 512 + maskPixel = (uchar*)(maskNorm.data + i * maskNorm.step + j); + if (*maskPixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *maskPixel; + } + } + } + + + uchar * irisFeaturePtr = new uchar[irisDataLength / 8 + 5]; + memset(irisFeaturePtr, 0, irisDataLength / 8 + 5); + + // first byte is width; + irisFeaturePtr[0] = (uchar)width; + irisFeaturePtr[1] = (uchar)(width >> 8); + + // second byte is height; + irisFeaturePtr[2] = (uchar)height; + + // third byte is n_codes + irisFeaturePtr[3] = (uchar)n_codes; + + // fourth byte is n_mask(1) + irisFeaturePtr[4] = (uchar)1; + for (int i = 0; i < irisDataLength; i++) { + irisFeaturePtr[5 + i / 8] += irisData[i] << (7 - (i % 8)); + } + + QByteArray feature; + for (int i = 0; i < irisDataLength / 8 + 5; i++) { + feature.append((char) irisFeaturePtr[i]); + } + + delete[] irisData; + delete[] irisFeaturePtr; + return feature; } float CasicIrisRec::matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2) @@ -283,6 +374,67 @@ } +float CasicIrisRec::matchFeatureCode(uchar *feature1, uchar *feature2) +{ + int width = feature1[0] | feature1[1] << 8; // 32 + int height = feature1[2]; // 8 + int nCode = feature1[3]; // 6 +// int nMask = feature1[4]; + + uchar ** irisData1 = reduceIrisCode(feature1); + uchar ** irisMask1 = reduceIrisMask(feature1); + uchar ** irisData2 = reduceIrisCode(feature2); + uchar ** irisMask2 = reduceIrisMask(feature2); + + int shift = 10; + float score = 1.0; + + int minstep = 0 - shift; + int maxstep = shift; + + for (int s = minstep; s <= maxstep; s++) { + int count = 0; + float mean = 0.0; + for (int n = 0; n < nCode; n++) { + for (auto pos : mvApplicationPoints) { + int row = pos.first / mvApplicationPoints[0].first - 1; + int col = (pos.second + s + width) % width; + + if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { + + uchar tmp1 = irisData1[row + height * n][col]; + uchar tmp2 = irisData2[row + height * n][pos.second]; + mean += tmp1 ^ tmp2; + count += 1; + } + } + } + + //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; + mean = mean / count; + score = mean < score ? mean : score; + + } + +// std::cout << "feature score: " << score << std::endl; + + +// for (int i = 0; i < height * nCode; i++) { +// delete irisData1[i]; +// delete irisData2[i]; +// } +// delete irisData1; +// delete irisData2; + +// for (int i = 0; i < height; i++) { +// delete irisMask1[i]; +// delete irisMask2[i]; +// } +// delete irisMask1; +// delete irisMask2; + return score; +} + cv::Mat CasicIrisRec::addBorders(cv::Mat pSrc, int width) { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); @@ -298,4 +450,39 @@ return result; } +uchar ** CasicIrisRec::reduceIrisCode(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2] * feature[3]; + + uchar ** reduceCode = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + reduceCode[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = i * width + j; + reduceCode[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return reduceCode; +} + +uchar ** CasicIrisRec::reduceIrisMask(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2]; // 8 + int nCode = feature[3]; // 6 + + uchar ** irisMask = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + irisMask[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = width * height * nCode + i * width + j; + irisMask[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return irisMask; +} + } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index f6ca8ac..2d9616e 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -5,6 +5,8 @@ #define NORM_HEIGHT 64 #define M_PI 3.1415926535897323846 +#include +#include #include namespace iristrt @@ -15,28 +17,28 @@ public: CasicIrisRec(); - CasicIrisRec(const char * gaborFilterFileName,const char * applicationPointsFileName); - ~CasicIrisRec(); cv::Mat normalize(cv::Mat image, int iris_x, int iris_y, int iris_r,int pupil_x, int pupil_y, int pupil_r); - cv::Mat encodeToImage(cv::Mat normalizedImage); + QByteArray extractFeature(cv::Mat irisCode, cv::Mat maskNorm); float matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2); + float matchFeatureCode(uchar * feature1, uchar * feature2); private: std::vector gaborFilters; - cv::Mat applicationPoints; + std::vector> mvApplicationPoints; std::vector loadGaborFilters(const char * gaborFilterFileName); - cv::Mat loadApplicationPoints(const char * applicationPointsFileName); cv::Mat addBorders(cv::Mat pSrc, int width); + uchar ** reduceIrisCode(uchar * feature); + uchar ** reduceIrisMask(uchar * feature); }; // end of class CasicIrisRec diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 37a0ed6..63eda4d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,3 +1,7 @@ +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + #include "IrisDataDao.h" IrisDataDao::IrisDataDao(QObject *parent) : BaseDao(parent) @@ -37,7 +41,7 @@ result.append(item); } -// LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } @@ -104,7 +108,7 @@ result.insert("right_iris_code3", query.value("right_iris_code3")); } -// LOG_DEBUG(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); + LOG_TRACE(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); return result; } @@ -114,7 +118,12 @@ // 新建查询 QSqlQuery query(ConnectionManager::getInstance()->getConnection()); - qulonglong id = ConnectionManager::getInstance()->generateId(); + qulonglong id; + if (object.contains("id") == true) { + id = object.value("id").toULongLong(); + } else { + id = ConnectionManager::getInstance()->generateId(); + } // INSERT语句 QString sql = QString("INSERT INTO IRIS_DATA (ID, PERSON_ID, ID_CARD_NO, LEFT_IRIS_CODE1, RIGHT_IRIS_CODE1) VALUES (:id, :personId, :idCardNo, :left1, :right1)"); @@ -132,7 +141,7 @@ // 执行插入 bool success = query.exec(); -// LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); + LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); // 结束事务 ConnectionManager::getInstance()->getConnection().commit(); diff --git a/dao/RecognitionRecordsDao.cpp b/dao/RecognitionRecordsDao.cpp index 40db453..d795039 100644 --- a/dao/RecognitionRecordsDao.cpp +++ b/dao/RecognitionRecordsDao.cpp @@ -1,4 +1,4 @@ -#include "RecognitionRecordsDao.h" +#include "RecognitionRecordsDao.h" RecognitionRecordsDao::RecognitionRecordsDao(QObject *parent) : BaseDao(parent) { @@ -58,10 +58,8 @@ query.bindValue(":doorCode", object.value("door_code").toString()); query.bindValue(":inoutType", object.value("inout_type").toString()); -// LOG_DEBUG(sql.toStdString()); - // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES (:id, :logInfo)"); + QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES (:id, :logInfo)"); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/dao/SysDictDao.cpp b/dao/SysDictDao.cpp new file mode 100644 index 0000000..7a2bc8b --- /dev/null +++ b/dao/SysDictDao.cpp @@ -0,0 +1,82 @@ +#include "SysDictDao.h" + + +SysDictDao::SysDictDao(QObject *parent) : BaseDao(parent) +{ + +} + +QVector SysDictDao::findAllRecord() +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT"; + + // 执行查询 + query.exec(sql); + + // 返回结果 + QVector result; + + // 遍历查询结果 + while (query.next()) { + QVariantMap item; + + item.insert("id", query.value("id").toLongLong()); + item.insert("code", query.value("code").toString()); + item.insert("name", query.value("name").toString()); + item.insert("pid", query.value("pid").toString()); + + result.append(item); + } + + return result; +} + +QVariantMap SysDictDao::findRecordById(QString id) +{ + QVariantMap item; + return item; +} + + +QVariantMap SysDictDao::findChildDictByCode(QString code) +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT where PID = (SELECT ID FROM SYS_DICT WHERE CODE = :code)"; + query.prepare(sql); + query.bindValue(":code", code); + + // 执行查询 + query.exec(); + + // 返回结果 + QVariantMap result; + + // 遍历查询结果 + while (query.next()) { + result.insert(query.value("code").toString(), query.value("name").toString()); + } + + return result; +} + +QString SysDictDao::save(QVariantMap object) +{ + return "0"; +} + +bool SysDictDao::edit(QVariantMap newObject, QString id) +{ + return false; +} + +bool SysDictDao::dele(QString id) +{ + return false; +} diff --git a/dao/SysDictDao.h b/dao/SysDictDao.h new file mode 100644 index 0000000..7c73aff --- /dev/null +++ b/dao/SysDictDao.h @@ -0,0 +1,23 @@ +#ifndef SYSDICTDAO_H +#define SYSDICTDAO_H + +#include +#include "BaseDao.h" + +class SysDictDao : public BaseDao +{ + Q_OBJECT +public: + explicit SysDictDao(QObject *parent = nullptr); + + QVector findAllRecord(); + QVariantMap findRecordById(QString id); + + QVariantMap findChildDictByCode(QString code); + + QString save(QVariantMap object); + bool edit(QVariantMap newObject, QString id); + bool dele(QString id); +}; + +#endif // SYSDICTDAO_H diff --git a/dao/SysPersonDao.cpp b/dao/SysPersonDao.cpp index dd9480f..19243b1 100644 --- a/dao/SysPersonDao.cpp +++ b/dao/SysPersonDao.cpp @@ -1,4 +1,4 @@ -#include "SysPersonDao.h" +#include "SysPersonDao.h" SysPersonDao::SysPersonDao(QObject *parent) : BaseDao(parent) @@ -56,10 +56,13 @@ QSqlQuery query(ConnectionManager::getInstance()->getConnection()); // 查询语句 - QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = '%1'").arg(id); + QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = :id"); + + query.prepare(sql); + query.bindValue(":id", id); // 执行查询 - query.exec(sql); + query.exec(); // 返回结果 QVariantMap result; @@ -84,8 +87,9 @@ result.insert("person_code", query.value("person_code").toString()); result.insert("deptname", query.value("fullname").toString()); result.insert("sync_id", query.value("sync_id").toString()); - result.insert("hasFace", query.value("face_valid").toString()); - result.insert("hasIris", query.value("iris_valid").toString()); + result.insert("avatar", query.value("avatar").toString()); +// result.insert("hasFace", query.value("face_valid").toString()); +// result.insert("hasIris", query.value("iris_valid").toString()); } // LOG(TRACE) << QString("根据id查询SYS_PERSON表的记录[id=%1][%2]").arg(id).arg(sql).toStdString(); diff --git a/dao/dao.pri b/dao/dao.pri index 1e04ce4..5f3b7f3 100644 --- a/dao/dao.pri +++ b/dao/dao.pri @@ -4,15 +4,17 @@ HEADERS += $$PWD/RecognitionRecordsDao.h HEADERS += $$PWD/SysPersonDao.h HEADERS += $$PWD/SysDeptDao.h +HEADERS += $$PWD/SysDictDao.h SOURCES += $$PWD/BaseDao.cpp SOURCES += $$PWD/IrisDataDao.cpp SOURCES += $$PWD/RecognitionRecordsDao.cpp SOURCES += $$PWD/SysPersonDao.cpp SOURCES += $$PWD/SysDeptDao.cpp +SOURCES += $$PWD/SysDictDao.cpp HEADERS += $$PWD/util/ConnectionManager.h SOURCES += $$PWD/util/ConnectionManager.cpp -#HEADERS += $$PWD/util/CacheManager.h -#SOURCES += $$PWD/util/CacheManager.cpp +HEADERS += $$PWD/util/CacheManager.h +SOURCES += $$PWD/util/CacheManager.cpp diff --git a/dao/util/CacheManager.cpp b/dao/util/CacheManager.cpp new file mode 100644 index 0000000..e415d93 --- /dev/null +++ b/dao/util/CacheManager.cpp @@ -0,0 +1,12 @@ +#include "CacheManager.h" + +CacheManager::CacheManager() +{ + SysDictDao dictDao; + genderName = dictDao.findChildDictByCode("gender"); +} + +QVariantMap CacheManager::getGenderName() +{ + return genderName; +} diff --git a/dao/util/CacheManager.h b/dao/util/CacheManager.h new file mode 100644 index 0000000..5226744 --- /dev/null +++ b/dao/util/CacheManager.h @@ -0,0 +1,31 @@ +#ifndef CACHEMANAGER_H +#define CACHEMANAGER_H + +#include +#include +#include "dao/SysDeptDao.h" +#include "dao/SysDictDao.h" +#include "dao/SysPersonDao.h" +#include "dao/IrisDataDao.h" + +class CacheManager +{ +public: + ~CacheManager() {}; + CacheManager(const CacheManager&)=delete; + CacheManager& operator=(const CacheManager&)=delete; + + static CacheManager& getInstance() { + static CacheManager instance; + return instance; + } + + QVariantMap getGenderName(); + +private: + CacheManager(); + + QVariantMap genderName; +}; + +#endif // CACHEMANAGER_H diff --git a/dao/util/ConnectionManager.cpp b/dao/util/ConnectionManager.cpp index 84b17be..fed7b8d 100644 --- a/dao/util/ConnectionManager.cpp +++ b/dao/util/ConnectionManager.cpp @@ -1,4 +1,8 @@ -#include "ConnectionManager.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ConnectionManager.h" #include Q_GLOBAL_STATIC(ConnectionManager, cm) @@ -18,10 +22,10 @@ bool succ = conn.open(); if (succ == true) { -// LOG_INFO(QString("打开数据库操作正常[Open Database Success]").toStdString()); + LOG_INFO(QString("打开数据库操作正常[Open Database Success]").toStdString()); } else { -// LOG_ERROR(QString("打开数据库操作失败[Open Database Failed]").toStdString()); + LOG_ERROR(QString("打开数据库操作失败[Open Database Failed]").toStdString()); } } } diff --git a/device/iris/CasicIrisRecState.cpp b/device/iris/CasicIrisRecState.cpp index 41105e1..c5e5f13 100644 --- a/device/iris/CasicIrisRecState.cpp +++ b/device/iris/CasicIrisRecState.cpp @@ -25,15 +25,43 @@ QDateTime now = QDateTime::currentDateTime(); this->recoginzeId = now.toString("yyyyMMddHHmmsszzz"); this->timeStamp = now.toMSecsSinceEpoch(); + this->timeStampSucc = 0; + this->tryCount = 0; this->noEyeCount = 0; + this->matchedId = ""; -// LOG(DEBUG) << QString("[CasicIrisRecState][initRecognize] 虹膜识别状态初始化").toStdString(); -// LOG_DEBUG(QString("[CasicIrisRecState][initRecognize] 虹膜识别状态初始化").toStdString()); + this->findEyeTmLast = 0; + this->segmentTmLast = 0; + this->extractTmLast = 0; + this->matchTmLast = 0; + this->recogTimeLast = 0; + + LOG_INFO(QString("[initRecognize][%1] 虹膜识别状态初始化").arg(recoginzeId).toStdString()); qDebug() << QString("[CasicIrisRecState][initRecognize][%1] 虹膜识别状态初始化").arg(recoginzeId); } +void CasicIrisRecState::restRecognize() +{ + this->recoginzeId = ""; + this->timeStamp = 0; + this->timeStampSucc = 0; + + this->tryCount = 0; + this->noEyeCount = 0; + + this->matchedId = ""; + this->score = 0.0f; + this->state = IrisRecStateName::REC_NOT_START; + + this->findEyeTmLast = 0; + this->segmentTmLast = 0; + this->extractTmLast = 0; + this->matchTmLast = 0; + this->recogTimeLast = 0; +} + QString CasicIrisRecState::toString() { return QString(QJsonDocument(toJSON()).toJson(QJsonDocument::Compact)); @@ -47,13 +75,19 @@ obj.insert("recoginzeId", recoginzeId); obj.insert("timestamp", timeStamp); obj.insert("timestampSucc", timeStampSucc); + obj.insert("state", state); + obj.insert("matchedId", matchedId); + obj.insert("score", score); + obj.insert("tryCount", tryCount); obj.insert("noEyeCount", noEyeCount); - obj.insert("recogTimeLast", recogTimeLast); - QJsonObject eyeObj; - eyeObj.insert("hasEye", irisInfo->hasEye); + obj.insert("recogTimeLast", recogTimeLast); + obj.insert("findEyeTmLast", findEyeTmLast); + obj.insert("segmentTmLast", segmentTmLast); + obj.insert("extractTmLast", extractTmLast); + obj.insert("matchTmLast", matchTmLast); return obj; } diff --git a/device/iris/CasicIrisRecState.h b/device/iris/CasicIrisRecState.h index 7506581..e978d58 100644 --- a/device/iris/CasicIrisRecState.h +++ b/device/iris/CasicIrisRecState.h @@ -22,6 +22,7 @@ } void initRecognize(); + void restRecognize(); QString toString(); QJsonObject toJSON(); @@ -29,6 +30,11 @@ qint64 timeStamp = 0; // 识别开始时间戳 qint64 timeStampSucc = 0; // 识别成功时的时间戳 qint64 findEyeTmLast = 0; // 找眼操作耗时 + qint64 segmentTmLast = 0; // 图像分割操作耗时 + qint64 extractTmLast = 0; // 编码操作耗时 + qint64 matchTmLast = 0; // 匹配操作耗时 + + float score = 0.0f; // 匹配评分 CasicIrisInfo * irisInfo; @@ -36,7 +42,7 @@ qint8 tryCount = 0; // 识别尝试次数 qint16 noEyeCount = 0; // 连续没有找到眼睛次数 - float recogTimeLast = 0.0; // 识别成功耗时 + qint16 recogTimeLast = 0.0; // 识别成功耗时ms /** * @brief state @@ -53,8 +59,6 @@ enum IrisRecStateName { REC_NOT_START = 0, // 未开始 - REC_LEFT_FIND_EYE = 1, // 检测左眼, 没找到右眼 - REC_RIGHT_FIND_EYE = 2, // 检测右眼, 没找到左眼 REC_FIND_EYE = 3, // 找到左眼和右眼 REC_FEATURE_EXTRACT = 4, // 特征值提取成功 REC_SEARCH_SUCC = 5, // 虹膜库比对成功 diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 5ca377e..38f54fe 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -62,10 +62,20 @@ // 3. 取出虹膜图像栈中的一条数据 CasicIrisInfo irisInfo = ProMemory::getInstance().popCasicIris(); - // 4. 调用找眼分类器算法 + QElapsedTimer timer; + timer.start(); + + // 4. 调用找眼分类器算法 第一阶段 casic::iris::CasicIrisInterface::getInstance().setMinEyeSize(SettingConfig::getInstance().MIN_EYE_SIZE); irisInfo = casic::iris::CasicIrisInterface::getInstance().findAndCutEye(irisInfo); + // 找眼计时 + int findEyeLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); + +// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.hasEye = true; + // 4.1 没有找到眼睛则返回 if (irisInfo.hasEye == false) { @@ -77,13 +87,13 @@ continue; } - // 4.2 找到眼睛则开始识别 + // 5. 找到眼睛则开始识别 // 发送信号更新界面 emit startIdentifyIris(); // 调用远程算法进行编码 - if (CasicIrisRecState::getInstance().recoginzeId == "0") + if (CasicIrisRecState::getInstance().recoginzeId == "0" || CasicIrisRecState::getInstance().recoginzeId == "") { // 第一次找到眼则 虹膜识别状态初始化 CasicIrisRecState::getInstance().initRecognize(); @@ -92,10 +102,14 @@ CasicIrisRecState::getInstance().noEyeCount = 0; // 持续未找到眼的次数清零 CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FIND_EYE; - QElapsedTimer timer; - timer.start(); + LOG_DEBUG(QString("[IrisRecogProcess step.1] 找眼及裁剪成功[%1 ms]").arg(findEyeLast).toStdString()); + CasicIrisRecState::getInstance().findEyeTmLast = findEyeLast; + CasicIrisRecState::getInstance().recogTimeLast += findEyeLast; - // 进行预处理 转换成 320 * 240 的三通道图像 送去压缩 + // 6. 分割图像 + timer.restart(); + + // 进行预处理 转换成 320 * 240 的三通道图像 送去分割 cv::Mat segMat; // 图像转换为RGB的彩色图像 @@ -108,7 +122,8 @@ // cv::imwrite(filename, segMat); // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - QByteArray data((char*)segMat.data, SettingConfig::getInstance().IRIS_WIDTH * 0.5 * SettingConfig::getInstance().IRIS_HEIGHT * 0.5 * 3); + int segMatSize = segMat.cols * segMat.rows; + QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 // 发送TCP消息去匹配 emit sendDataToExract(data); @@ -131,27 +146,27 @@ char recvMask[320 * 240 * 1]; char recvIris[320 * 240 * 1]; memset(recvPupil, 0, sizeof(recvPupil)); - memset(recvMask, 0, sizeof(recvMask)); - memset(recvIris, 0, sizeof(recvIris)); + memset(recvMask, 0, sizeof (recvMask)); + memset(recvIris, 0, sizeof (recvIris)); for (int i = 0; i < clientUtil->getResponse().size(); i++) { - if (i < 320 * 240) + if (i < segMatSize) recvPupil[i] = clientUtil->getResponse().at(i); - else if (i >= 320 * 240 && i < 2 * 320 * 240) - recvMask[i - 320 * 240] = clientUtil->getResponse().at(i); + else if (i >= segMatSize && i < 2 * segMatSize) + recvMask[i - segMatSize] = clientUtil->getResponse().at(i); else - recvIris[i - 2 * 320 * 240] = clientUtil->getResponse().at(i); + recvIris[i - 2 * segMatSize] = clientUtil->getResponse().at(i); } - // 成功接收后清除缓存区 - clientUtil->resetRecvBuffer(); - - cv::Mat pupil(240, 320, CV_8UC1, recvPupil); - cv::Mat mask(240, 320, CV_8UC1, recvMask); - cv::Mat iris(240, 320, CV_8UC1, recvIris); + cv::Mat pupil(segMat.rows, segMat.cols, CV_8UC1, recvPupil); + cv::Mat mask(segMat.rows, segMat.cols, CV_8UC1, recvMask); + cv::Mat iris(segMat.rows, segMat.cols, CV_8UC1, recvIris); irisInfo.segResult.innerMask = pupil; irisInfo.segResult.irisMask = mask; irisInfo.segResult.outerCircle = iris; - /* + + // 成功接收后清除缓存区 + 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(); @@ -159,9 +174,15 @@ cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); */ - qDebug() << QString("算法分割图像成功[%1 ms]").arg(timer.elapsed()); + // 第二阶段 分割图像计时 + int segLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 算法分割图像成功[%1 ms]").arg(segLast); + LOG_DEBUG(QString("[IrisRecogProcess step.2] 算法分割图像成功[%1 ms]").arg(segLast).toStdString()); + CasicIrisRecState::getInstance().segmentTmLast = segLast; + CasicIrisRecState::getInstance().recogTimeLast += segLast; - // 分割后的后处理 + // 7. 分割后的后处理 编码及提取特征值 + timer.restart(); if (cv::countNonZero(mask) == 0 || cv::countNonZero(pupil) == 0|| cv::countNonZero(iris) == 0) { qDebug() << "算法分割图像失败,暂停200ms"; @@ -173,38 +194,53 @@ // 状态修改为特征提取 CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; - - timer.restart(); 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")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); +/* + 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(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); +*/ - qDebug() << QString("虹膜图像编码成功[%1 ms]").arg(timer.elapsed()); + // 从编码中提取特征值 + irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); + + int encodeLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 虹膜图像编码并提取特征值成功[%1 ms]").arg(encodeLast); + LOG_DEBUG(QString("[IrisRecogProcess step.3] 虹膜图像编码并提取特征值成功[%1 ms]").arg(encodeLast).toStdString()); + CasicIrisRecState::getInstance().extractTmLast = encodeLast; + CasicIrisRecState::getInstance().recogTimeLast += encodeLast; // 开始匹配 + timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) { CasicIrisFeature feature = ProMemory::getInstance().getIrisFeatures().at(i); - float score = casic::iris::CasicIrisInterface::getInstance().calculateMatchScore(feature, irisInfo); - // SpeakerUtil::getInstance().speak(QString::number(score)); - cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).arg(score).toStdString(), irisInfo.matData); + + 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); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; + CasicIrisRecState::getInstance().score = score; + CasicIrisRecState::getInstance().timeStampSucc = QDateTime::currentMSecsSinceEpoch(); + break ; } } + int matchLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 虹膜库匹配[%1 ms][%2]").arg(matchLast).arg(CasicIrisRecState::getInstance().state); + LOG_DEBUG(QString("[IrisRecogProcess step.4] 虹膜库匹配[%1 ms][%2]").arg(matchLast).arg(CasicIrisRecState::getInstance().state).toStdString()); + CasicIrisRecState::getInstance().matchTmLast = matchLast; + CasicIrisRecState::getInstance().recogTimeLast += matchLast; + if (CasicIrisRecState::getInstance().state == CasicIrisRecState::REC_SEARCH_SUCC) { // 找到匹配结果 - emit findMatchedIris(CasicIrisRecState::getInstance().matchedId); + afterRecogAction(); - ProMemory::getInstance().irisCam->stopCapture(); - ProMemory::getInstance().clearIrisQueue(); - this->setWorking(false); + emit findMatchedIris(CasicIrisRecState::getInstance().matchedId); } else { // 没有匹配上 addOneTryCount(); @@ -215,7 +251,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - + ProMemory::getInstance().irisCam->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } diff --git a/utils/LogUtil.h b/utils/LogUtil.h new file mode 100644 index 0000000..eb4147c --- /dev/null +++ b/utils/LogUtil.h @@ -0,0 +1,87 @@ +#ifndef LOGUTIL_H +#define LOGUTIL_H + +#include "spdlog/spdlog.h" +#include "spdlog/sinks/daily_file_sink.h" + +#include "SettingConfig.h" + +// use embedded macro to support file and line number +#define LOG_TRACE(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::trace, __VA_ARGS__) +#define LOG_DEBUG(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::debug, __VA_ARGS__) +#define LOG_INFO(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::info, __VA_ARGS__) +#define LOG_WARN(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::warn, __VA_ARGS__) +#define LOG_ERROR(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::err, __VA_ARGS__) + + +class LogUtil +{ +public: + ~LogUtil() + { + spdlog::drop_all(); + } + + LogUtil(const LogUtil&)=delete; + LogUtil& operator=(const LogUtil&)=delete; //禁止生成默认赋值函数 + + // magic singleton static + static LogUtil* getInstance() { + static LogUtil instance; + return &instance; + } + + std::shared_ptr getLogger() + { + return m_logger; + } + +private: + LogUtil() + { + try { + + // Create a daily logger - a new file is created every day on 00:00am + m_logger = spdlog::daily_logger_mt("CasicIrisIdentify", SettingConfig::getInstance().LOG_FILE.toStdString(), 0, 0); + + m_logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e][%l] %v"); + + std::string level = SettingConfig::getInstance().LOG_LEVEL.toStdString(); + if (level == "trace") + { + m_logger->set_level(spdlog::level::trace); + m_logger->flush_on(spdlog::level::trace); + } + else if (level == "debug") + { + m_logger->set_level(spdlog::level::debug); + m_logger->flush_on(spdlog::level::debug); + } + else if (level == "info") + { + m_logger->set_level(spdlog::level::info); + m_logger->flush_on(spdlog::level::info); + } + else if (level == "warn") + { + m_logger->set_level(spdlog::level::warn); + m_logger->flush_on(spdlog::level::warn); + } + else if (level == "error") + { + m_logger->set_level(spdlog::level::err); + m_logger->flush_on(spdlog::level::err); + } + } + catch (const spdlog::spdlog_ex& ex) + { + spdlog::error("init log failed: {}",ex.what()); + + } + } + + std::shared_ptr m_logger; + +}; + +#endif // LOGUTIL_H diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp index 4b321c1..663db0f 100644 --- a/utils/SettingConfig.cpp +++ b/utils/SettingConfig.cpp @@ -12,6 +12,7 @@ WINDOW_TITLE = getProperty("window", "title").toString(); WINDOW_RIGHTS = getProperty("window", "copyright").toString(); WINDOW_VERSION = getProperty("window", "version").toString(); + DEVICE_CODE = getProperty("window", "deviceCode").toString(); IRIS_FRAME_WIDTH = getProperty("camera", "irisFrameWidth").toInt(); IRIS_FRAME_HEIGHT = getProperty("camera", "irisFrameHeight").toInt(); diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index 1558461..c528381 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -87,9 +87,6 @@ this->cascade->load(cascadeName); } - QElapsedTimer timer; - timer.start(); - std::vector rect; cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); @@ -111,8 +108,8 @@ // .arg(timer.elapsed()).arg(rect.size()) // .arg(rect.at(0).x).arg(rect.at(0).y) // .arg(rect.at(0).width).arg(rect.at(0).height).toStdString()); - qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]") - .arg(timer.elapsed()).arg(rect.size()) + qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]") + .arg(rect.size()) .arg(rect.at(0).x).arg(rect.at(0).y) .arg(rect.at(0).width).arg(rect.at(0).height); @@ -141,20 +138,18 @@ } // 裁剪眼部图像 - cv::Mat halfSize = irisInfo.matData.clone(); - halfSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, + cv::Mat cutSize = irisInfo.matData.clone(); + cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5, SettingConfig::getInstance().IRIS_WIDTH * cutRatio, SettingConfig::getInstance().IRIS_HEIGHT * cutRatio)); - cv::resize(halfSize, halfSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); - cv::flip(halfSize, halfSize, 1); // 左右翻转 + // 裁剪后放大到 640 * 480 + cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); + cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; -// irisInfo.eyeRect = rect.at(0); - - irisInfo.matData = halfSize; -// irisInfo.data = ImageUtil::MatImageToQImage(halfSize); + irisInfo.matData = cutSize; return irisInfo; } @@ -229,9 +224,18 @@ return irisInfo; } +QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo) +{ + QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm); + return irisFeatureCode; +} + float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo) { -// cv::imshow("info", irisInfo.irisCode); -// cv::waitKey(0); return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm); } + +float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other) +{ + return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data())); +} diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index cbee8fe..26fbedc 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -27,7 +27,9 @@ CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); + QByteArray extractFeature(CasicIrisInfo irisInfo); float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo); + float calculatePairPoints(QByteArray feature, QByteArray other); void setCascadeFile(QString filename); void setMinEyeSize(int minEyeSize); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index c8ffe3e..ad456b4 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -177,6 +177,8 @@ // Get the coordinates file >> i; file >> j; + mvApplicationPoints.push_back(QPair(i, j)); + // Set pixel to "on" if (i < 0 || i > applicationPoints.rows - 1 || j < 0 || j > applicationPoints.cols- 1) { @@ -237,7 +239,96 @@ roi.copyTo(dst); //cv::copyTo(img2, dst, NULL); } - return encodeImage; + cv::Mat image8UC1; + encodeImage.convertTo(image8UC1, CV_8UC1); + return image8UC1; +} + +QByteArray CasicIrisRec::extractFeature(cv::Mat irisCode, cv::Mat maskNorm) +{ + // count points width and height + cv::Mat pointTemp(applicationPoints); + cv::Mat rowTemp; + + std::vector pointRows; + for (int i = 0; i < applicationPoints.rows; i++) { + rowTemp = pointTemp(cv::Rect(0, i, applicationPoints.cols, 1)); + if (cv::sum(rowTemp)[0] > 0) { + pointRows.push_back(i); + } + } + + int width = irisCode.cols; + int height = pointRows.size(); + rowTemp.release(); + pointTemp.release(); + + int n_codes = irisCode.rows / applicationPoints.rows; + + int irisDataLength = (n_codes + 1) * width * height; + uchar * irisData = new uchar[irisDataLength]; + int irisDataIndex = 0; + + uchar* codePixel = new uchar; + + // save iris code 512 * 8 * 6 + for (int n = 0; n < n_codes; n++) { // 6 + for (auto i : pointRows) { // 8 + i = n * maskNorm.rows + i; + for (int j = 0; j < irisCode.cols; j++) { // 512 + codePixel = (uchar*)(irisCode.data + i * irisCode.step + j); + if (*codePixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *codePixel; + } + } + } + } + + // save iris mask 512 * 8 * 1 + uchar * maskPixel; + for (auto i : pointRows) { // 8 + for (int j = 0; j < irisCode.cols; j++) { // 512 + maskPixel = (uchar*)(maskNorm.data + i * maskNorm.step + j); + if (*maskPixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *maskPixel; + } + } + } + + + uchar * irisFeaturePtr = new uchar[irisDataLength / 8 + 5]; + memset(irisFeaturePtr, 0, irisDataLength / 8 + 5); + + // first byte is width; + irisFeaturePtr[0] = (uchar)width; + irisFeaturePtr[1] = (uchar)(width >> 8); + + // second byte is height; + irisFeaturePtr[2] = (uchar)height; + + // third byte is n_codes + irisFeaturePtr[3] = (uchar)n_codes; + + // fourth byte is n_mask(1) + irisFeaturePtr[4] = (uchar)1; + for (int i = 0; i < irisDataLength; i++) { + irisFeaturePtr[5 + i / 8] += irisData[i] << (7 - (i % 8)); + } + + QByteArray feature; + for (int i = 0; i < irisDataLength / 8 + 5; i++) { + feature.append((char) irisFeaturePtr[i]); + } + + delete[] irisData; + delete[] irisFeaturePtr; + return feature; } float CasicIrisRec::matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2) @@ -283,6 +374,67 @@ } +float CasicIrisRec::matchFeatureCode(uchar *feature1, uchar *feature2) +{ + int width = feature1[0] | feature1[1] << 8; // 32 + int height = feature1[2]; // 8 + int nCode = feature1[3]; // 6 +// int nMask = feature1[4]; + + uchar ** irisData1 = reduceIrisCode(feature1); + uchar ** irisMask1 = reduceIrisMask(feature1); + uchar ** irisData2 = reduceIrisCode(feature2); + uchar ** irisMask2 = reduceIrisMask(feature2); + + int shift = 10; + float score = 1.0; + + int minstep = 0 - shift; + int maxstep = shift; + + for (int s = minstep; s <= maxstep; s++) { + int count = 0; + float mean = 0.0; + for (int n = 0; n < nCode; n++) { + for (auto pos : mvApplicationPoints) { + int row = pos.first / mvApplicationPoints[0].first - 1; + int col = (pos.second + s + width) % width; + + if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { + + uchar tmp1 = irisData1[row + height * n][col]; + uchar tmp2 = irisData2[row + height * n][pos.second]; + mean += tmp1 ^ tmp2; + count += 1; + } + } + } + + //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; + mean = mean / count; + score = mean < score ? mean : score; + + } + +// std::cout << "feature score: " << score << std::endl; + + +// for (int i = 0; i < height * nCode; i++) { +// delete irisData1[i]; +// delete irisData2[i]; +// } +// delete irisData1; +// delete irisData2; + +// for (int i = 0; i < height; i++) { +// delete irisMask1[i]; +// delete irisMask2[i]; +// } +// delete irisMask1; +// delete irisMask2; + return score; +} + cv::Mat CasicIrisRec::addBorders(cv::Mat pSrc, int width) { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); @@ -298,4 +450,39 @@ return result; } +uchar ** CasicIrisRec::reduceIrisCode(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2] * feature[3]; + + uchar ** reduceCode = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + reduceCode[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = i * width + j; + reduceCode[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return reduceCode; +} + +uchar ** CasicIrisRec::reduceIrisMask(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2]; // 8 + int nCode = feature[3]; // 6 + + uchar ** irisMask = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + irisMask[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = width * height * nCode + i * width + j; + irisMask[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return irisMask; +} + } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index f6ca8ac..2d9616e 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -5,6 +5,8 @@ #define NORM_HEIGHT 64 #define M_PI 3.1415926535897323846 +#include +#include #include namespace iristrt @@ -15,28 +17,28 @@ public: CasicIrisRec(); - CasicIrisRec(const char * gaborFilterFileName,const char * applicationPointsFileName); - ~CasicIrisRec(); cv::Mat normalize(cv::Mat image, int iris_x, int iris_y, int iris_r,int pupil_x, int pupil_y, int pupil_r); - cv::Mat encodeToImage(cv::Mat normalizedImage); + QByteArray extractFeature(cv::Mat irisCode, cv::Mat maskNorm); float matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2); + float matchFeatureCode(uchar * feature1, uchar * feature2); private: std::vector gaborFilters; - cv::Mat applicationPoints; + std::vector> mvApplicationPoints; std::vector loadGaborFilters(const char * gaborFilterFileName); - cv::Mat loadApplicationPoints(const char * applicationPointsFileName); cv::Mat addBorders(cv::Mat pSrc, int width); + uchar ** reduceIrisCode(uchar * feature); + uchar ** reduceIrisMask(uchar * feature); }; // end of class CasicIrisRec diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 37a0ed6..63eda4d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,3 +1,7 @@ +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + #include "IrisDataDao.h" IrisDataDao::IrisDataDao(QObject *parent) : BaseDao(parent) @@ -37,7 +41,7 @@ result.append(item); } -// LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } @@ -104,7 +108,7 @@ result.insert("right_iris_code3", query.value("right_iris_code3")); } -// LOG_DEBUG(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); + LOG_TRACE(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); return result; } @@ -114,7 +118,12 @@ // 新建查询 QSqlQuery query(ConnectionManager::getInstance()->getConnection()); - qulonglong id = ConnectionManager::getInstance()->generateId(); + qulonglong id; + if (object.contains("id") == true) { + id = object.value("id").toULongLong(); + } else { + id = ConnectionManager::getInstance()->generateId(); + } // INSERT语句 QString sql = QString("INSERT INTO IRIS_DATA (ID, PERSON_ID, ID_CARD_NO, LEFT_IRIS_CODE1, RIGHT_IRIS_CODE1) VALUES (:id, :personId, :idCardNo, :left1, :right1)"); @@ -132,7 +141,7 @@ // 执行插入 bool success = query.exec(); -// LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); + LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); // 结束事务 ConnectionManager::getInstance()->getConnection().commit(); diff --git a/dao/RecognitionRecordsDao.cpp b/dao/RecognitionRecordsDao.cpp index 40db453..d795039 100644 --- a/dao/RecognitionRecordsDao.cpp +++ b/dao/RecognitionRecordsDao.cpp @@ -1,4 +1,4 @@ -#include "RecognitionRecordsDao.h" +#include "RecognitionRecordsDao.h" RecognitionRecordsDao::RecognitionRecordsDao(QObject *parent) : BaseDao(parent) { @@ -58,10 +58,8 @@ query.bindValue(":doorCode", object.value("door_code").toString()); query.bindValue(":inoutType", object.value("inout_type").toString()); -// LOG_DEBUG(sql.toStdString()); - // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES (:id, :logInfo)"); + QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES (:id, :logInfo)"); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/dao/SysDictDao.cpp b/dao/SysDictDao.cpp new file mode 100644 index 0000000..7a2bc8b --- /dev/null +++ b/dao/SysDictDao.cpp @@ -0,0 +1,82 @@ +#include "SysDictDao.h" + + +SysDictDao::SysDictDao(QObject *parent) : BaseDao(parent) +{ + +} + +QVector SysDictDao::findAllRecord() +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT"; + + // 执行查询 + query.exec(sql); + + // 返回结果 + QVector result; + + // 遍历查询结果 + while (query.next()) { + QVariantMap item; + + item.insert("id", query.value("id").toLongLong()); + item.insert("code", query.value("code").toString()); + item.insert("name", query.value("name").toString()); + item.insert("pid", query.value("pid").toString()); + + result.append(item); + } + + return result; +} + +QVariantMap SysDictDao::findRecordById(QString id) +{ + QVariantMap item; + return item; +} + + +QVariantMap SysDictDao::findChildDictByCode(QString code) +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT where PID = (SELECT ID FROM SYS_DICT WHERE CODE = :code)"; + query.prepare(sql); + query.bindValue(":code", code); + + // 执行查询 + query.exec(); + + // 返回结果 + QVariantMap result; + + // 遍历查询结果 + while (query.next()) { + result.insert(query.value("code").toString(), query.value("name").toString()); + } + + return result; +} + +QString SysDictDao::save(QVariantMap object) +{ + return "0"; +} + +bool SysDictDao::edit(QVariantMap newObject, QString id) +{ + return false; +} + +bool SysDictDao::dele(QString id) +{ + return false; +} diff --git a/dao/SysDictDao.h b/dao/SysDictDao.h new file mode 100644 index 0000000..7c73aff --- /dev/null +++ b/dao/SysDictDao.h @@ -0,0 +1,23 @@ +#ifndef SYSDICTDAO_H +#define SYSDICTDAO_H + +#include +#include "BaseDao.h" + +class SysDictDao : public BaseDao +{ + Q_OBJECT +public: + explicit SysDictDao(QObject *parent = nullptr); + + QVector findAllRecord(); + QVariantMap findRecordById(QString id); + + QVariantMap findChildDictByCode(QString code); + + QString save(QVariantMap object); + bool edit(QVariantMap newObject, QString id); + bool dele(QString id); +}; + +#endif // SYSDICTDAO_H diff --git a/dao/SysPersonDao.cpp b/dao/SysPersonDao.cpp index dd9480f..19243b1 100644 --- a/dao/SysPersonDao.cpp +++ b/dao/SysPersonDao.cpp @@ -1,4 +1,4 @@ -#include "SysPersonDao.h" +#include "SysPersonDao.h" SysPersonDao::SysPersonDao(QObject *parent) : BaseDao(parent) @@ -56,10 +56,13 @@ QSqlQuery query(ConnectionManager::getInstance()->getConnection()); // 查询语句 - QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = '%1'").arg(id); + QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = :id"); + + query.prepare(sql); + query.bindValue(":id", id); // 执行查询 - query.exec(sql); + query.exec(); // 返回结果 QVariantMap result; @@ -84,8 +87,9 @@ result.insert("person_code", query.value("person_code").toString()); result.insert("deptname", query.value("fullname").toString()); result.insert("sync_id", query.value("sync_id").toString()); - result.insert("hasFace", query.value("face_valid").toString()); - result.insert("hasIris", query.value("iris_valid").toString()); + result.insert("avatar", query.value("avatar").toString()); +// result.insert("hasFace", query.value("face_valid").toString()); +// result.insert("hasIris", query.value("iris_valid").toString()); } // LOG(TRACE) << QString("根据id查询SYS_PERSON表的记录[id=%1][%2]").arg(id).arg(sql).toStdString(); diff --git a/dao/dao.pri b/dao/dao.pri index 1e04ce4..5f3b7f3 100644 --- a/dao/dao.pri +++ b/dao/dao.pri @@ -4,15 +4,17 @@ HEADERS += $$PWD/RecognitionRecordsDao.h HEADERS += $$PWD/SysPersonDao.h HEADERS += $$PWD/SysDeptDao.h +HEADERS += $$PWD/SysDictDao.h SOURCES += $$PWD/BaseDao.cpp SOURCES += $$PWD/IrisDataDao.cpp SOURCES += $$PWD/RecognitionRecordsDao.cpp SOURCES += $$PWD/SysPersonDao.cpp SOURCES += $$PWD/SysDeptDao.cpp +SOURCES += $$PWD/SysDictDao.cpp HEADERS += $$PWD/util/ConnectionManager.h SOURCES += $$PWD/util/ConnectionManager.cpp -#HEADERS += $$PWD/util/CacheManager.h -#SOURCES += $$PWD/util/CacheManager.cpp +HEADERS += $$PWD/util/CacheManager.h +SOURCES += $$PWD/util/CacheManager.cpp diff --git a/dao/util/CacheManager.cpp b/dao/util/CacheManager.cpp new file mode 100644 index 0000000..e415d93 --- /dev/null +++ b/dao/util/CacheManager.cpp @@ -0,0 +1,12 @@ +#include "CacheManager.h" + +CacheManager::CacheManager() +{ + SysDictDao dictDao; + genderName = dictDao.findChildDictByCode("gender"); +} + +QVariantMap CacheManager::getGenderName() +{ + return genderName; +} diff --git a/dao/util/CacheManager.h b/dao/util/CacheManager.h new file mode 100644 index 0000000..5226744 --- /dev/null +++ b/dao/util/CacheManager.h @@ -0,0 +1,31 @@ +#ifndef CACHEMANAGER_H +#define CACHEMANAGER_H + +#include +#include +#include "dao/SysDeptDao.h" +#include "dao/SysDictDao.h" +#include "dao/SysPersonDao.h" +#include "dao/IrisDataDao.h" + +class CacheManager +{ +public: + ~CacheManager() {}; + CacheManager(const CacheManager&)=delete; + CacheManager& operator=(const CacheManager&)=delete; + + static CacheManager& getInstance() { + static CacheManager instance; + return instance; + } + + QVariantMap getGenderName(); + +private: + CacheManager(); + + QVariantMap genderName; +}; + +#endif // CACHEMANAGER_H diff --git a/dao/util/ConnectionManager.cpp b/dao/util/ConnectionManager.cpp index 84b17be..fed7b8d 100644 --- a/dao/util/ConnectionManager.cpp +++ b/dao/util/ConnectionManager.cpp @@ -1,4 +1,8 @@ -#include "ConnectionManager.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ConnectionManager.h" #include Q_GLOBAL_STATIC(ConnectionManager, cm) @@ -18,10 +22,10 @@ bool succ = conn.open(); if (succ == true) { -// LOG_INFO(QString("打开数据库操作正常[Open Database Success]").toStdString()); + LOG_INFO(QString("打开数据库操作正常[Open Database Success]").toStdString()); } else { -// LOG_ERROR(QString("打开数据库操作失败[Open Database Failed]").toStdString()); + LOG_ERROR(QString("打开数据库操作失败[Open Database Failed]").toStdString()); } } } diff --git a/device/iris/CasicIrisRecState.cpp b/device/iris/CasicIrisRecState.cpp index 41105e1..c5e5f13 100644 --- a/device/iris/CasicIrisRecState.cpp +++ b/device/iris/CasicIrisRecState.cpp @@ -25,15 +25,43 @@ QDateTime now = QDateTime::currentDateTime(); this->recoginzeId = now.toString("yyyyMMddHHmmsszzz"); this->timeStamp = now.toMSecsSinceEpoch(); + this->timeStampSucc = 0; + this->tryCount = 0; this->noEyeCount = 0; + this->matchedId = ""; -// LOG(DEBUG) << QString("[CasicIrisRecState][initRecognize] 虹膜识别状态初始化").toStdString(); -// LOG_DEBUG(QString("[CasicIrisRecState][initRecognize] 虹膜识别状态初始化").toStdString()); + this->findEyeTmLast = 0; + this->segmentTmLast = 0; + this->extractTmLast = 0; + this->matchTmLast = 0; + this->recogTimeLast = 0; + + LOG_INFO(QString("[initRecognize][%1] 虹膜识别状态初始化").arg(recoginzeId).toStdString()); qDebug() << QString("[CasicIrisRecState][initRecognize][%1] 虹膜识别状态初始化").arg(recoginzeId); } +void CasicIrisRecState::restRecognize() +{ + this->recoginzeId = ""; + this->timeStamp = 0; + this->timeStampSucc = 0; + + this->tryCount = 0; + this->noEyeCount = 0; + + this->matchedId = ""; + this->score = 0.0f; + this->state = IrisRecStateName::REC_NOT_START; + + this->findEyeTmLast = 0; + this->segmentTmLast = 0; + this->extractTmLast = 0; + this->matchTmLast = 0; + this->recogTimeLast = 0; +} + QString CasicIrisRecState::toString() { return QString(QJsonDocument(toJSON()).toJson(QJsonDocument::Compact)); @@ -47,13 +75,19 @@ obj.insert("recoginzeId", recoginzeId); obj.insert("timestamp", timeStamp); obj.insert("timestampSucc", timeStampSucc); + obj.insert("state", state); + obj.insert("matchedId", matchedId); + obj.insert("score", score); + obj.insert("tryCount", tryCount); obj.insert("noEyeCount", noEyeCount); - obj.insert("recogTimeLast", recogTimeLast); - QJsonObject eyeObj; - eyeObj.insert("hasEye", irisInfo->hasEye); + obj.insert("recogTimeLast", recogTimeLast); + obj.insert("findEyeTmLast", findEyeTmLast); + obj.insert("segmentTmLast", segmentTmLast); + obj.insert("extractTmLast", extractTmLast); + obj.insert("matchTmLast", matchTmLast); return obj; } diff --git a/device/iris/CasicIrisRecState.h b/device/iris/CasicIrisRecState.h index 7506581..e978d58 100644 --- a/device/iris/CasicIrisRecState.h +++ b/device/iris/CasicIrisRecState.h @@ -22,6 +22,7 @@ } void initRecognize(); + void restRecognize(); QString toString(); QJsonObject toJSON(); @@ -29,6 +30,11 @@ qint64 timeStamp = 0; // 识别开始时间戳 qint64 timeStampSucc = 0; // 识别成功时的时间戳 qint64 findEyeTmLast = 0; // 找眼操作耗时 + qint64 segmentTmLast = 0; // 图像分割操作耗时 + qint64 extractTmLast = 0; // 编码操作耗时 + qint64 matchTmLast = 0; // 匹配操作耗时 + + float score = 0.0f; // 匹配评分 CasicIrisInfo * irisInfo; @@ -36,7 +42,7 @@ qint8 tryCount = 0; // 识别尝试次数 qint16 noEyeCount = 0; // 连续没有找到眼睛次数 - float recogTimeLast = 0.0; // 识别成功耗时 + qint16 recogTimeLast = 0.0; // 识别成功耗时ms /** * @brief state @@ -53,8 +59,6 @@ enum IrisRecStateName { REC_NOT_START = 0, // 未开始 - REC_LEFT_FIND_EYE = 1, // 检测左眼, 没找到右眼 - REC_RIGHT_FIND_EYE = 2, // 检测右眼, 没找到左眼 REC_FIND_EYE = 3, // 找到左眼和右眼 REC_FEATURE_EXTRACT = 4, // 特征值提取成功 REC_SEARCH_SUCC = 5, // 虹膜库比对成功 diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 5ca377e..38f54fe 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -62,10 +62,20 @@ // 3. 取出虹膜图像栈中的一条数据 CasicIrisInfo irisInfo = ProMemory::getInstance().popCasicIris(); - // 4. 调用找眼分类器算法 + QElapsedTimer timer; + timer.start(); + + // 4. 调用找眼分类器算法 第一阶段 casic::iris::CasicIrisInterface::getInstance().setMinEyeSize(SettingConfig::getInstance().MIN_EYE_SIZE); irisInfo = casic::iris::CasicIrisInterface::getInstance().findAndCutEye(irisInfo); + // 找眼计时 + int findEyeLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); + +// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.hasEye = true; + // 4.1 没有找到眼睛则返回 if (irisInfo.hasEye == false) { @@ -77,13 +87,13 @@ continue; } - // 4.2 找到眼睛则开始识别 + // 5. 找到眼睛则开始识别 // 发送信号更新界面 emit startIdentifyIris(); // 调用远程算法进行编码 - if (CasicIrisRecState::getInstance().recoginzeId == "0") + if (CasicIrisRecState::getInstance().recoginzeId == "0" || CasicIrisRecState::getInstance().recoginzeId == "") { // 第一次找到眼则 虹膜识别状态初始化 CasicIrisRecState::getInstance().initRecognize(); @@ -92,10 +102,14 @@ CasicIrisRecState::getInstance().noEyeCount = 0; // 持续未找到眼的次数清零 CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FIND_EYE; - QElapsedTimer timer; - timer.start(); + LOG_DEBUG(QString("[IrisRecogProcess step.1] 找眼及裁剪成功[%1 ms]").arg(findEyeLast).toStdString()); + CasicIrisRecState::getInstance().findEyeTmLast = findEyeLast; + CasicIrisRecState::getInstance().recogTimeLast += findEyeLast; - // 进行预处理 转换成 320 * 240 的三通道图像 送去压缩 + // 6. 分割图像 + timer.restart(); + + // 进行预处理 转换成 320 * 240 的三通道图像 送去分割 cv::Mat segMat; // 图像转换为RGB的彩色图像 @@ -108,7 +122,8 @@ // cv::imwrite(filename, segMat); // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - QByteArray data((char*)segMat.data, SettingConfig::getInstance().IRIS_WIDTH * 0.5 * SettingConfig::getInstance().IRIS_HEIGHT * 0.5 * 3); + int segMatSize = segMat.cols * segMat.rows; + QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 // 发送TCP消息去匹配 emit sendDataToExract(data); @@ -131,27 +146,27 @@ char recvMask[320 * 240 * 1]; char recvIris[320 * 240 * 1]; memset(recvPupil, 0, sizeof(recvPupil)); - memset(recvMask, 0, sizeof(recvMask)); - memset(recvIris, 0, sizeof(recvIris)); + memset(recvMask, 0, sizeof (recvMask)); + memset(recvIris, 0, sizeof (recvIris)); for (int i = 0; i < clientUtil->getResponse().size(); i++) { - if (i < 320 * 240) + if (i < segMatSize) recvPupil[i] = clientUtil->getResponse().at(i); - else if (i >= 320 * 240 && i < 2 * 320 * 240) - recvMask[i - 320 * 240] = clientUtil->getResponse().at(i); + else if (i >= segMatSize && i < 2 * segMatSize) + recvMask[i - segMatSize] = clientUtil->getResponse().at(i); else - recvIris[i - 2 * 320 * 240] = clientUtil->getResponse().at(i); + recvIris[i - 2 * segMatSize] = clientUtil->getResponse().at(i); } - // 成功接收后清除缓存区 - clientUtil->resetRecvBuffer(); - - cv::Mat pupil(240, 320, CV_8UC1, recvPupil); - cv::Mat mask(240, 320, CV_8UC1, recvMask); - cv::Mat iris(240, 320, CV_8UC1, recvIris); + cv::Mat pupil(segMat.rows, segMat.cols, CV_8UC1, recvPupil); + cv::Mat mask(segMat.rows, segMat.cols, CV_8UC1, recvMask); + cv::Mat iris(segMat.rows, segMat.cols, CV_8UC1, recvIris); irisInfo.segResult.innerMask = pupil; irisInfo.segResult.irisMask = mask; irisInfo.segResult.outerCircle = iris; - /* + + // 成功接收后清除缓存区 + 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(); @@ -159,9 +174,15 @@ cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); */ - qDebug() << QString("算法分割图像成功[%1 ms]").arg(timer.elapsed()); + // 第二阶段 分割图像计时 + int segLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 算法分割图像成功[%1 ms]").arg(segLast); + LOG_DEBUG(QString("[IrisRecogProcess step.2] 算法分割图像成功[%1 ms]").arg(segLast).toStdString()); + CasicIrisRecState::getInstance().segmentTmLast = segLast; + CasicIrisRecState::getInstance().recogTimeLast += segLast; - // 分割后的后处理 + // 7. 分割后的后处理 编码及提取特征值 + timer.restart(); if (cv::countNonZero(mask) == 0 || cv::countNonZero(pupil) == 0|| cv::countNonZero(iris) == 0) { qDebug() << "算法分割图像失败,暂停200ms"; @@ -173,38 +194,53 @@ // 状态修改为特征提取 CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; - - timer.restart(); 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")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); +/* + 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(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); +*/ - qDebug() << QString("虹膜图像编码成功[%1 ms]").arg(timer.elapsed()); + // 从编码中提取特征值 + irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); + + int encodeLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 虹膜图像编码并提取特征值成功[%1 ms]").arg(encodeLast); + LOG_DEBUG(QString("[IrisRecogProcess step.3] 虹膜图像编码并提取特征值成功[%1 ms]").arg(encodeLast).toStdString()); + CasicIrisRecState::getInstance().extractTmLast = encodeLast; + CasicIrisRecState::getInstance().recogTimeLast += encodeLast; // 开始匹配 + timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) { CasicIrisFeature feature = ProMemory::getInstance().getIrisFeatures().at(i); - float score = casic::iris::CasicIrisInterface::getInstance().calculateMatchScore(feature, irisInfo); - // SpeakerUtil::getInstance().speak(QString::number(score)); - cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).arg(score).toStdString(), irisInfo.matData); + + 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); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; + CasicIrisRecState::getInstance().score = score; + CasicIrisRecState::getInstance().timeStampSucc = QDateTime::currentMSecsSinceEpoch(); + break ; } } + int matchLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 虹膜库匹配[%1 ms][%2]").arg(matchLast).arg(CasicIrisRecState::getInstance().state); + LOG_DEBUG(QString("[IrisRecogProcess step.4] 虹膜库匹配[%1 ms][%2]").arg(matchLast).arg(CasicIrisRecState::getInstance().state).toStdString()); + CasicIrisRecState::getInstance().matchTmLast = matchLast; + CasicIrisRecState::getInstance().recogTimeLast += matchLast; + if (CasicIrisRecState::getInstance().state == CasicIrisRecState::REC_SEARCH_SUCC) { // 找到匹配结果 - emit findMatchedIris(CasicIrisRecState::getInstance().matchedId); + afterRecogAction(); - ProMemory::getInstance().irisCam->stopCapture(); - ProMemory::getInstance().clearIrisQueue(); - this->setWorking(false); + emit findMatchedIris(CasicIrisRecState::getInstance().matchedId); } else { // 没有匹配上 addOneTryCount(); @@ -215,7 +251,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - + ProMemory::getInstance().irisCam->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } diff --git a/utils/LogUtil.h b/utils/LogUtil.h new file mode 100644 index 0000000..eb4147c --- /dev/null +++ b/utils/LogUtil.h @@ -0,0 +1,87 @@ +#ifndef LOGUTIL_H +#define LOGUTIL_H + +#include "spdlog/spdlog.h" +#include "spdlog/sinks/daily_file_sink.h" + +#include "SettingConfig.h" + +// use embedded macro to support file and line number +#define LOG_TRACE(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::trace, __VA_ARGS__) +#define LOG_DEBUG(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::debug, __VA_ARGS__) +#define LOG_INFO(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::info, __VA_ARGS__) +#define LOG_WARN(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::warn, __VA_ARGS__) +#define LOG_ERROR(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::err, __VA_ARGS__) + + +class LogUtil +{ +public: + ~LogUtil() + { + spdlog::drop_all(); + } + + LogUtil(const LogUtil&)=delete; + LogUtil& operator=(const LogUtil&)=delete; //禁止生成默认赋值函数 + + // magic singleton static + static LogUtil* getInstance() { + static LogUtil instance; + return &instance; + } + + std::shared_ptr getLogger() + { + return m_logger; + } + +private: + LogUtil() + { + try { + + // Create a daily logger - a new file is created every day on 00:00am + m_logger = spdlog::daily_logger_mt("CasicIrisIdentify", SettingConfig::getInstance().LOG_FILE.toStdString(), 0, 0); + + m_logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e][%l] %v"); + + std::string level = SettingConfig::getInstance().LOG_LEVEL.toStdString(); + if (level == "trace") + { + m_logger->set_level(spdlog::level::trace); + m_logger->flush_on(spdlog::level::trace); + } + else if (level == "debug") + { + m_logger->set_level(spdlog::level::debug); + m_logger->flush_on(spdlog::level::debug); + } + else if (level == "info") + { + m_logger->set_level(spdlog::level::info); + m_logger->flush_on(spdlog::level::info); + } + else if (level == "warn") + { + m_logger->set_level(spdlog::level::warn); + m_logger->flush_on(spdlog::level::warn); + } + else if (level == "error") + { + m_logger->set_level(spdlog::level::err); + m_logger->flush_on(spdlog::level::err); + } + } + catch (const spdlog::spdlog_ex& ex) + { + spdlog::error("init log failed: {}",ex.what()); + + } + } + + std::shared_ptr m_logger; + +}; + +#endif // LOGUTIL_H diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp index 4b321c1..663db0f 100644 --- a/utils/SettingConfig.cpp +++ b/utils/SettingConfig.cpp @@ -12,6 +12,7 @@ WINDOW_TITLE = getProperty("window", "title").toString(); WINDOW_RIGHTS = getProperty("window", "copyright").toString(); WINDOW_VERSION = getProperty("window", "version").toString(); + DEVICE_CODE = getProperty("window", "deviceCode").toString(); IRIS_FRAME_WIDTH = getProperty("camera", "irisFrameWidth").toInt(); IRIS_FRAME_HEIGHT = getProperty("camera", "irisFrameHeight").toInt(); diff --git a/utils/SettingConfig.h b/utils/SettingConfig.h index 852b151..b65f553 100644 --- a/utils/SettingConfig.h +++ b/utils/SettingConfig.h @@ -32,6 +32,7 @@ QString WINDOW_TITLE; QString WINDOW_RIGHTS; QString WINDOW_VERSION; + QString DEVICE_CODE; int IRIS_FRAME_INTERVAL; int IRIS_FRAME_WIDTH; diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index 1558461..c528381 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -87,9 +87,6 @@ this->cascade->load(cascadeName); } - QElapsedTimer timer; - timer.start(); - std::vector rect; cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); @@ -111,8 +108,8 @@ // .arg(timer.elapsed()).arg(rect.size()) // .arg(rect.at(0).x).arg(rect.at(0).y) // .arg(rect.at(0).width).arg(rect.at(0).height).toStdString()); - qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]") - .arg(timer.elapsed()).arg(rect.size()) + qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]") + .arg(rect.size()) .arg(rect.at(0).x).arg(rect.at(0).y) .arg(rect.at(0).width).arg(rect.at(0).height); @@ -141,20 +138,18 @@ } // 裁剪眼部图像 - cv::Mat halfSize = irisInfo.matData.clone(); - halfSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, + cv::Mat cutSize = irisInfo.matData.clone(); + cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5, SettingConfig::getInstance().IRIS_WIDTH * cutRatio, SettingConfig::getInstance().IRIS_HEIGHT * cutRatio)); - cv::resize(halfSize, halfSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); - cv::flip(halfSize, halfSize, 1); // 左右翻转 + // 裁剪后放大到 640 * 480 + cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); + cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; -// irisInfo.eyeRect = rect.at(0); - - irisInfo.matData = halfSize; -// irisInfo.data = ImageUtil::MatImageToQImage(halfSize); + irisInfo.matData = cutSize; return irisInfo; } @@ -229,9 +224,18 @@ return irisInfo; } +QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo) +{ + QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm); + return irisFeatureCode; +} + float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo) { -// cv::imshow("info", irisInfo.irisCode); -// cv::waitKey(0); return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm); } + +float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other) +{ + return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data())); +} diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index cbee8fe..26fbedc 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -27,7 +27,9 @@ CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); + QByteArray extractFeature(CasicIrisInfo irisInfo); float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo); + float calculatePairPoints(QByteArray feature, QByteArray other); void setCascadeFile(QString filename); void setMinEyeSize(int minEyeSize); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index c8ffe3e..ad456b4 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -177,6 +177,8 @@ // Get the coordinates file >> i; file >> j; + mvApplicationPoints.push_back(QPair(i, j)); + // Set pixel to "on" if (i < 0 || i > applicationPoints.rows - 1 || j < 0 || j > applicationPoints.cols- 1) { @@ -237,7 +239,96 @@ roi.copyTo(dst); //cv::copyTo(img2, dst, NULL); } - return encodeImage; + cv::Mat image8UC1; + encodeImage.convertTo(image8UC1, CV_8UC1); + return image8UC1; +} + +QByteArray CasicIrisRec::extractFeature(cv::Mat irisCode, cv::Mat maskNorm) +{ + // count points width and height + cv::Mat pointTemp(applicationPoints); + cv::Mat rowTemp; + + std::vector pointRows; + for (int i = 0; i < applicationPoints.rows; i++) { + rowTemp = pointTemp(cv::Rect(0, i, applicationPoints.cols, 1)); + if (cv::sum(rowTemp)[0] > 0) { + pointRows.push_back(i); + } + } + + int width = irisCode.cols; + int height = pointRows.size(); + rowTemp.release(); + pointTemp.release(); + + int n_codes = irisCode.rows / applicationPoints.rows; + + int irisDataLength = (n_codes + 1) * width * height; + uchar * irisData = new uchar[irisDataLength]; + int irisDataIndex = 0; + + uchar* codePixel = new uchar; + + // save iris code 512 * 8 * 6 + for (int n = 0; n < n_codes; n++) { // 6 + for (auto i : pointRows) { // 8 + i = n * maskNorm.rows + i; + for (int j = 0; j < irisCode.cols; j++) { // 512 + codePixel = (uchar*)(irisCode.data + i * irisCode.step + j); + if (*codePixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *codePixel; + } + } + } + } + + // save iris mask 512 * 8 * 1 + uchar * maskPixel; + for (auto i : pointRows) { // 8 + for (int j = 0; j < irisCode.cols; j++) { // 512 + maskPixel = (uchar*)(maskNorm.data + i * maskNorm.step + j); + if (*maskPixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *maskPixel; + } + } + } + + + uchar * irisFeaturePtr = new uchar[irisDataLength / 8 + 5]; + memset(irisFeaturePtr, 0, irisDataLength / 8 + 5); + + // first byte is width; + irisFeaturePtr[0] = (uchar)width; + irisFeaturePtr[1] = (uchar)(width >> 8); + + // second byte is height; + irisFeaturePtr[2] = (uchar)height; + + // third byte is n_codes + irisFeaturePtr[3] = (uchar)n_codes; + + // fourth byte is n_mask(1) + irisFeaturePtr[4] = (uchar)1; + for (int i = 0; i < irisDataLength; i++) { + irisFeaturePtr[5 + i / 8] += irisData[i] << (7 - (i % 8)); + } + + QByteArray feature; + for (int i = 0; i < irisDataLength / 8 + 5; i++) { + feature.append((char) irisFeaturePtr[i]); + } + + delete[] irisData; + delete[] irisFeaturePtr; + return feature; } float CasicIrisRec::matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2) @@ -283,6 +374,67 @@ } +float CasicIrisRec::matchFeatureCode(uchar *feature1, uchar *feature2) +{ + int width = feature1[0] | feature1[1] << 8; // 32 + int height = feature1[2]; // 8 + int nCode = feature1[3]; // 6 +// int nMask = feature1[4]; + + uchar ** irisData1 = reduceIrisCode(feature1); + uchar ** irisMask1 = reduceIrisMask(feature1); + uchar ** irisData2 = reduceIrisCode(feature2); + uchar ** irisMask2 = reduceIrisMask(feature2); + + int shift = 10; + float score = 1.0; + + int minstep = 0 - shift; + int maxstep = shift; + + for (int s = minstep; s <= maxstep; s++) { + int count = 0; + float mean = 0.0; + for (int n = 0; n < nCode; n++) { + for (auto pos : mvApplicationPoints) { + int row = pos.first / mvApplicationPoints[0].first - 1; + int col = (pos.second + s + width) % width; + + if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { + + uchar tmp1 = irisData1[row + height * n][col]; + uchar tmp2 = irisData2[row + height * n][pos.second]; + mean += tmp1 ^ tmp2; + count += 1; + } + } + } + + //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; + mean = mean / count; + score = mean < score ? mean : score; + + } + +// std::cout << "feature score: " << score << std::endl; + + +// for (int i = 0; i < height * nCode; i++) { +// delete irisData1[i]; +// delete irisData2[i]; +// } +// delete irisData1; +// delete irisData2; + +// for (int i = 0; i < height; i++) { +// delete irisMask1[i]; +// delete irisMask2[i]; +// } +// delete irisMask1; +// delete irisMask2; + return score; +} + cv::Mat CasicIrisRec::addBorders(cv::Mat pSrc, int width) { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); @@ -298,4 +450,39 @@ return result; } +uchar ** CasicIrisRec::reduceIrisCode(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2] * feature[3]; + + uchar ** reduceCode = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + reduceCode[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = i * width + j; + reduceCode[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return reduceCode; +} + +uchar ** CasicIrisRec::reduceIrisMask(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2]; // 8 + int nCode = feature[3]; // 6 + + uchar ** irisMask = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + irisMask[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = width * height * nCode + i * width + j; + irisMask[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return irisMask; +} + } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index f6ca8ac..2d9616e 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -5,6 +5,8 @@ #define NORM_HEIGHT 64 #define M_PI 3.1415926535897323846 +#include +#include #include namespace iristrt @@ -15,28 +17,28 @@ public: CasicIrisRec(); - CasicIrisRec(const char * gaborFilterFileName,const char * applicationPointsFileName); - ~CasicIrisRec(); cv::Mat normalize(cv::Mat image, int iris_x, int iris_y, int iris_r,int pupil_x, int pupil_y, int pupil_r); - cv::Mat encodeToImage(cv::Mat normalizedImage); + QByteArray extractFeature(cv::Mat irisCode, cv::Mat maskNorm); float matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2); + float matchFeatureCode(uchar * feature1, uchar * feature2); private: std::vector gaborFilters; - cv::Mat applicationPoints; + std::vector> mvApplicationPoints; std::vector loadGaborFilters(const char * gaborFilterFileName); - cv::Mat loadApplicationPoints(const char * applicationPointsFileName); cv::Mat addBorders(cv::Mat pSrc, int width); + uchar ** reduceIrisCode(uchar * feature); + uchar ** reduceIrisMask(uchar * feature); }; // end of class CasicIrisRec diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 37a0ed6..63eda4d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,3 +1,7 @@ +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + #include "IrisDataDao.h" IrisDataDao::IrisDataDao(QObject *parent) : BaseDao(parent) @@ -37,7 +41,7 @@ result.append(item); } -// LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } @@ -104,7 +108,7 @@ result.insert("right_iris_code3", query.value("right_iris_code3")); } -// LOG_DEBUG(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); + LOG_TRACE(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); return result; } @@ -114,7 +118,12 @@ // 新建查询 QSqlQuery query(ConnectionManager::getInstance()->getConnection()); - qulonglong id = ConnectionManager::getInstance()->generateId(); + qulonglong id; + if (object.contains("id") == true) { + id = object.value("id").toULongLong(); + } else { + id = ConnectionManager::getInstance()->generateId(); + } // INSERT语句 QString sql = QString("INSERT INTO IRIS_DATA (ID, PERSON_ID, ID_CARD_NO, LEFT_IRIS_CODE1, RIGHT_IRIS_CODE1) VALUES (:id, :personId, :idCardNo, :left1, :right1)"); @@ -132,7 +141,7 @@ // 执行插入 bool success = query.exec(); -// LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); + LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); // 结束事务 ConnectionManager::getInstance()->getConnection().commit(); diff --git a/dao/RecognitionRecordsDao.cpp b/dao/RecognitionRecordsDao.cpp index 40db453..d795039 100644 --- a/dao/RecognitionRecordsDao.cpp +++ b/dao/RecognitionRecordsDao.cpp @@ -1,4 +1,4 @@ -#include "RecognitionRecordsDao.h" +#include "RecognitionRecordsDao.h" RecognitionRecordsDao::RecognitionRecordsDao(QObject *parent) : BaseDao(parent) { @@ -58,10 +58,8 @@ query.bindValue(":doorCode", object.value("door_code").toString()); query.bindValue(":inoutType", object.value("inout_type").toString()); -// LOG_DEBUG(sql.toStdString()); - // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES (:id, :logInfo)"); + QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES (:id, :logInfo)"); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/dao/SysDictDao.cpp b/dao/SysDictDao.cpp new file mode 100644 index 0000000..7a2bc8b --- /dev/null +++ b/dao/SysDictDao.cpp @@ -0,0 +1,82 @@ +#include "SysDictDao.h" + + +SysDictDao::SysDictDao(QObject *parent) : BaseDao(parent) +{ + +} + +QVector SysDictDao::findAllRecord() +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT"; + + // 执行查询 + query.exec(sql); + + // 返回结果 + QVector result; + + // 遍历查询结果 + while (query.next()) { + QVariantMap item; + + item.insert("id", query.value("id").toLongLong()); + item.insert("code", query.value("code").toString()); + item.insert("name", query.value("name").toString()); + item.insert("pid", query.value("pid").toString()); + + result.append(item); + } + + return result; +} + +QVariantMap SysDictDao::findRecordById(QString id) +{ + QVariantMap item; + return item; +} + + +QVariantMap SysDictDao::findChildDictByCode(QString code) +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT where PID = (SELECT ID FROM SYS_DICT WHERE CODE = :code)"; + query.prepare(sql); + query.bindValue(":code", code); + + // 执行查询 + query.exec(); + + // 返回结果 + QVariantMap result; + + // 遍历查询结果 + while (query.next()) { + result.insert(query.value("code").toString(), query.value("name").toString()); + } + + return result; +} + +QString SysDictDao::save(QVariantMap object) +{ + return "0"; +} + +bool SysDictDao::edit(QVariantMap newObject, QString id) +{ + return false; +} + +bool SysDictDao::dele(QString id) +{ + return false; +} diff --git a/dao/SysDictDao.h b/dao/SysDictDao.h new file mode 100644 index 0000000..7c73aff --- /dev/null +++ b/dao/SysDictDao.h @@ -0,0 +1,23 @@ +#ifndef SYSDICTDAO_H +#define SYSDICTDAO_H + +#include +#include "BaseDao.h" + +class SysDictDao : public BaseDao +{ + Q_OBJECT +public: + explicit SysDictDao(QObject *parent = nullptr); + + QVector findAllRecord(); + QVariantMap findRecordById(QString id); + + QVariantMap findChildDictByCode(QString code); + + QString save(QVariantMap object); + bool edit(QVariantMap newObject, QString id); + bool dele(QString id); +}; + +#endif // SYSDICTDAO_H diff --git a/dao/SysPersonDao.cpp b/dao/SysPersonDao.cpp index dd9480f..19243b1 100644 --- a/dao/SysPersonDao.cpp +++ b/dao/SysPersonDao.cpp @@ -1,4 +1,4 @@ -#include "SysPersonDao.h" +#include "SysPersonDao.h" SysPersonDao::SysPersonDao(QObject *parent) : BaseDao(parent) @@ -56,10 +56,13 @@ QSqlQuery query(ConnectionManager::getInstance()->getConnection()); // 查询语句 - QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = '%1'").arg(id); + QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = :id"); + + query.prepare(sql); + query.bindValue(":id", id); // 执行查询 - query.exec(sql); + query.exec(); // 返回结果 QVariantMap result; @@ -84,8 +87,9 @@ result.insert("person_code", query.value("person_code").toString()); result.insert("deptname", query.value("fullname").toString()); result.insert("sync_id", query.value("sync_id").toString()); - result.insert("hasFace", query.value("face_valid").toString()); - result.insert("hasIris", query.value("iris_valid").toString()); + result.insert("avatar", query.value("avatar").toString()); +// result.insert("hasFace", query.value("face_valid").toString()); +// result.insert("hasIris", query.value("iris_valid").toString()); } // LOG(TRACE) << QString("根据id查询SYS_PERSON表的记录[id=%1][%2]").arg(id).arg(sql).toStdString(); diff --git a/dao/dao.pri b/dao/dao.pri index 1e04ce4..5f3b7f3 100644 --- a/dao/dao.pri +++ b/dao/dao.pri @@ -4,15 +4,17 @@ HEADERS += $$PWD/RecognitionRecordsDao.h HEADERS += $$PWD/SysPersonDao.h HEADERS += $$PWD/SysDeptDao.h +HEADERS += $$PWD/SysDictDao.h SOURCES += $$PWD/BaseDao.cpp SOURCES += $$PWD/IrisDataDao.cpp SOURCES += $$PWD/RecognitionRecordsDao.cpp SOURCES += $$PWD/SysPersonDao.cpp SOURCES += $$PWD/SysDeptDao.cpp +SOURCES += $$PWD/SysDictDao.cpp HEADERS += $$PWD/util/ConnectionManager.h SOURCES += $$PWD/util/ConnectionManager.cpp -#HEADERS += $$PWD/util/CacheManager.h -#SOURCES += $$PWD/util/CacheManager.cpp +HEADERS += $$PWD/util/CacheManager.h +SOURCES += $$PWD/util/CacheManager.cpp diff --git a/dao/util/CacheManager.cpp b/dao/util/CacheManager.cpp new file mode 100644 index 0000000..e415d93 --- /dev/null +++ b/dao/util/CacheManager.cpp @@ -0,0 +1,12 @@ +#include "CacheManager.h" + +CacheManager::CacheManager() +{ + SysDictDao dictDao; + genderName = dictDao.findChildDictByCode("gender"); +} + +QVariantMap CacheManager::getGenderName() +{ + return genderName; +} diff --git a/dao/util/CacheManager.h b/dao/util/CacheManager.h new file mode 100644 index 0000000..5226744 --- /dev/null +++ b/dao/util/CacheManager.h @@ -0,0 +1,31 @@ +#ifndef CACHEMANAGER_H +#define CACHEMANAGER_H + +#include +#include +#include "dao/SysDeptDao.h" +#include "dao/SysDictDao.h" +#include "dao/SysPersonDao.h" +#include "dao/IrisDataDao.h" + +class CacheManager +{ +public: + ~CacheManager() {}; + CacheManager(const CacheManager&)=delete; + CacheManager& operator=(const CacheManager&)=delete; + + static CacheManager& getInstance() { + static CacheManager instance; + return instance; + } + + QVariantMap getGenderName(); + +private: + CacheManager(); + + QVariantMap genderName; +}; + +#endif // CACHEMANAGER_H diff --git a/dao/util/ConnectionManager.cpp b/dao/util/ConnectionManager.cpp index 84b17be..fed7b8d 100644 --- a/dao/util/ConnectionManager.cpp +++ b/dao/util/ConnectionManager.cpp @@ -1,4 +1,8 @@ -#include "ConnectionManager.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ConnectionManager.h" #include Q_GLOBAL_STATIC(ConnectionManager, cm) @@ -18,10 +22,10 @@ bool succ = conn.open(); if (succ == true) { -// LOG_INFO(QString("打开数据库操作正常[Open Database Success]").toStdString()); + LOG_INFO(QString("打开数据库操作正常[Open Database Success]").toStdString()); } else { -// LOG_ERROR(QString("打开数据库操作失败[Open Database Failed]").toStdString()); + LOG_ERROR(QString("打开数据库操作失败[Open Database Failed]").toStdString()); } } } diff --git a/device/iris/CasicIrisRecState.cpp b/device/iris/CasicIrisRecState.cpp index 41105e1..c5e5f13 100644 --- a/device/iris/CasicIrisRecState.cpp +++ b/device/iris/CasicIrisRecState.cpp @@ -25,15 +25,43 @@ QDateTime now = QDateTime::currentDateTime(); this->recoginzeId = now.toString("yyyyMMddHHmmsszzz"); this->timeStamp = now.toMSecsSinceEpoch(); + this->timeStampSucc = 0; + this->tryCount = 0; this->noEyeCount = 0; + this->matchedId = ""; -// LOG(DEBUG) << QString("[CasicIrisRecState][initRecognize] 虹膜识别状态初始化").toStdString(); -// LOG_DEBUG(QString("[CasicIrisRecState][initRecognize] 虹膜识别状态初始化").toStdString()); + this->findEyeTmLast = 0; + this->segmentTmLast = 0; + this->extractTmLast = 0; + this->matchTmLast = 0; + this->recogTimeLast = 0; + + LOG_INFO(QString("[initRecognize][%1] 虹膜识别状态初始化").arg(recoginzeId).toStdString()); qDebug() << QString("[CasicIrisRecState][initRecognize][%1] 虹膜识别状态初始化").arg(recoginzeId); } +void CasicIrisRecState::restRecognize() +{ + this->recoginzeId = ""; + this->timeStamp = 0; + this->timeStampSucc = 0; + + this->tryCount = 0; + this->noEyeCount = 0; + + this->matchedId = ""; + this->score = 0.0f; + this->state = IrisRecStateName::REC_NOT_START; + + this->findEyeTmLast = 0; + this->segmentTmLast = 0; + this->extractTmLast = 0; + this->matchTmLast = 0; + this->recogTimeLast = 0; +} + QString CasicIrisRecState::toString() { return QString(QJsonDocument(toJSON()).toJson(QJsonDocument::Compact)); @@ -47,13 +75,19 @@ obj.insert("recoginzeId", recoginzeId); obj.insert("timestamp", timeStamp); obj.insert("timestampSucc", timeStampSucc); + obj.insert("state", state); + obj.insert("matchedId", matchedId); + obj.insert("score", score); + obj.insert("tryCount", tryCount); obj.insert("noEyeCount", noEyeCount); - obj.insert("recogTimeLast", recogTimeLast); - QJsonObject eyeObj; - eyeObj.insert("hasEye", irisInfo->hasEye); + obj.insert("recogTimeLast", recogTimeLast); + obj.insert("findEyeTmLast", findEyeTmLast); + obj.insert("segmentTmLast", segmentTmLast); + obj.insert("extractTmLast", extractTmLast); + obj.insert("matchTmLast", matchTmLast); return obj; } diff --git a/device/iris/CasicIrisRecState.h b/device/iris/CasicIrisRecState.h index 7506581..e978d58 100644 --- a/device/iris/CasicIrisRecState.h +++ b/device/iris/CasicIrisRecState.h @@ -22,6 +22,7 @@ } void initRecognize(); + void restRecognize(); QString toString(); QJsonObject toJSON(); @@ -29,6 +30,11 @@ qint64 timeStamp = 0; // 识别开始时间戳 qint64 timeStampSucc = 0; // 识别成功时的时间戳 qint64 findEyeTmLast = 0; // 找眼操作耗时 + qint64 segmentTmLast = 0; // 图像分割操作耗时 + qint64 extractTmLast = 0; // 编码操作耗时 + qint64 matchTmLast = 0; // 匹配操作耗时 + + float score = 0.0f; // 匹配评分 CasicIrisInfo * irisInfo; @@ -36,7 +42,7 @@ qint8 tryCount = 0; // 识别尝试次数 qint16 noEyeCount = 0; // 连续没有找到眼睛次数 - float recogTimeLast = 0.0; // 识别成功耗时 + qint16 recogTimeLast = 0.0; // 识别成功耗时ms /** * @brief state @@ -53,8 +59,6 @@ enum IrisRecStateName { REC_NOT_START = 0, // 未开始 - REC_LEFT_FIND_EYE = 1, // 检测左眼, 没找到右眼 - REC_RIGHT_FIND_EYE = 2, // 检测右眼, 没找到左眼 REC_FIND_EYE = 3, // 找到左眼和右眼 REC_FEATURE_EXTRACT = 4, // 特征值提取成功 REC_SEARCH_SUCC = 5, // 虹膜库比对成功 diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 5ca377e..38f54fe 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -62,10 +62,20 @@ // 3. 取出虹膜图像栈中的一条数据 CasicIrisInfo irisInfo = ProMemory::getInstance().popCasicIris(); - // 4. 调用找眼分类器算法 + QElapsedTimer timer; + timer.start(); + + // 4. 调用找眼分类器算法 第一阶段 casic::iris::CasicIrisInterface::getInstance().setMinEyeSize(SettingConfig::getInstance().MIN_EYE_SIZE); irisInfo = casic::iris::CasicIrisInterface::getInstance().findAndCutEye(irisInfo); + // 找眼计时 + int findEyeLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); + +// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.hasEye = true; + // 4.1 没有找到眼睛则返回 if (irisInfo.hasEye == false) { @@ -77,13 +87,13 @@ continue; } - // 4.2 找到眼睛则开始识别 + // 5. 找到眼睛则开始识别 // 发送信号更新界面 emit startIdentifyIris(); // 调用远程算法进行编码 - if (CasicIrisRecState::getInstance().recoginzeId == "0") + if (CasicIrisRecState::getInstance().recoginzeId == "0" || CasicIrisRecState::getInstance().recoginzeId == "") { // 第一次找到眼则 虹膜识别状态初始化 CasicIrisRecState::getInstance().initRecognize(); @@ -92,10 +102,14 @@ CasicIrisRecState::getInstance().noEyeCount = 0; // 持续未找到眼的次数清零 CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FIND_EYE; - QElapsedTimer timer; - timer.start(); + LOG_DEBUG(QString("[IrisRecogProcess step.1] 找眼及裁剪成功[%1 ms]").arg(findEyeLast).toStdString()); + CasicIrisRecState::getInstance().findEyeTmLast = findEyeLast; + CasicIrisRecState::getInstance().recogTimeLast += findEyeLast; - // 进行预处理 转换成 320 * 240 的三通道图像 送去压缩 + // 6. 分割图像 + timer.restart(); + + // 进行预处理 转换成 320 * 240 的三通道图像 送去分割 cv::Mat segMat; // 图像转换为RGB的彩色图像 @@ -108,7 +122,8 @@ // cv::imwrite(filename, segMat); // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - QByteArray data((char*)segMat.data, SettingConfig::getInstance().IRIS_WIDTH * 0.5 * SettingConfig::getInstance().IRIS_HEIGHT * 0.5 * 3); + int segMatSize = segMat.cols * segMat.rows; + QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 // 发送TCP消息去匹配 emit sendDataToExract(data); @@ -131,27 +146,27 @@ char recvMask[320 * 240 * 1]; char recvIris[320 * 240 * 1]; memset(recvPupil, 0, sizeof(recvPupil)); - memset(recvMask, 0, sizeof(recvMask)); - memset(recvIris, 0, sizeof(recvIris)); + memset(recvMask, 0, sizeof (recvMask)); + memset(recvIris, 0, sizeof (recvIris)); for (int i = 0; i < clientUtil->getResponse().size(); i++) { - if (i < 320 * 240) + if (i < segMatSize) recvPupil[i] = clientUtil->getResponse().at(i); - else if (i >= 320 * 240 && i < 2 * 320 * 240) - recvMask[i - 320 * 240] = clientUtil->getResponse().at(i); + else if (i >= segMatSize && i < 2 * segMatSize) + recvMask[i - segMatSize] = clientUtil->getResponse().at(i); else - recvIris[i - 2 * 320 * 240] = clientUtil->getResponse().at(i); + recvIris[i - 2 * segMatSize] = clientUtil->getResponse().at(i); } - // 成功接收后清除缓存区 - clientUtil->resetRecvBuffer(); - - cv::Mat pupil(240, 320, CV_8UC1, recvPupil); - cv::Mat mask(240, 320, CV_8UC1, recvMask); - cv::Mat iris(240, 320, CV_8UC1, recvIris); + cv::Mat pupil(segMat.rows, segMat.cols, CV_8UC1, recvPupil); + cv::Mat mask(segMat.rows, segMat.cols, CV_8UC1, recvMask); + cv::Mat iris(segMat.rows, segMat.cols, CV_8UC1, recvIris); irisInfo.segResult.innerMask = pupil; irisInfo.segResult.irisMask = mask; irisInfo.segResult.outerCircle = iris; - /* + + // 成功接收后清除缓存区 + 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(); @@ -159,9 +174,15 @@ cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); */ - qDebug() << QString("算法分割图像成功[%1 ms]").arg(timer.elapsed()); + // 第二阶段 分割图像计时 + int segLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 算法分割图像成功[%1 ms]").arg(segLast); + LOG_DEBUG(QString("[IrisRecogProcess step.2] 算法分割图像成功[%1 ms]").arg(segLast).toStdString()); + CasicIrisRecState::getInstance().segmentTmLast = segLast; + CasicIrisRecState::getInstance().recogTimeLast += segLast; - // 分割后的后处理 + // 7. 分割后的后处理 编码及提取特征值 + timer.restart(); if (cv::countNonZero(mask) == 0 || cv::countNonZero(pupil) == 0|| cv::countNonZero(iris) == 0) { qDebug() << "算法分割图像失败,暂停200ms"; @@ -173,38 +194,53 @@ // 状态修改为特征提取 CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; - - timer.restart(); 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")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); +/* + 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(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); +*/ - qDebug() << QString("虹膜图像编码成功[%1 ms]").arg(timer.elapsed()); + // 从编码中提取特征值 + irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); + + int encodeLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 虹膜图像编码并提取特征值成功[%1 ms]").arg(encodeLast); + LOG_DEBUG(QString("[IrisRecogProcess step.3] 虹膜图像编码并提取特征值成功[%1 ms]").arg(encodeLast).toStdString()); + CasicIrisRecState::getInstance().extractTmLast = encodeLast; + CasicIrisRecState::getInstance().recogTimeLast += encodeLast; // 开始匹配 + timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) { CasicIrisFeature feature = ProMemory::getInstance().getIrisFeatures().at(i); - float score = casic::iris::CasicIrisInterface::getInstance().calculateMatchScore(feature, irisInfo); - // SpeakerUtil::getInstance().speak(QString::number(score)); - cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).arg(score).toStdString(), irisInfo.matData); + + 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); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; + CasicIrisRecState::getInstance().score = score; + CasicIrisRecState::getInstance().timeStampSucc = QDateTime::currentMSecsSinceEpoch(); + break ; } } + int matchLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 虹膜库匹配[%1 ms][%2]").arg(matchLast).arg(CasicIrisRecState::getInstance().state); + LOG_DEBUG(QString("[IrisRecogProcess step.4] 虹膜库匹配[%1 ms][%2]").arg(matchLast).arg(CasicIrisRecState::getInstance().state).toStdString()); + CasicIrisRecState::getInstance().matchTmLast = matchLast; + CasicIrisRecState::getInstance().recogTimeLast += matchLast; + if (CasicIrisRecState::getInstance().state == CasicIrisRecState::REC_SEARCH_SUCC) { // 找到匹配结果 - emit findMatchedIris(CasicIrisRecState::getInstance().matchedId); + afterRecogAction(); - ProMemory::getInstance().irisCam->stopCapture(); - ProMemory::getInstance().clearIrisQueue(); - this->setWorking(false); + emit findMatchedIris(CasicIrisRecState::getInstance().matchedId); } else { // 没有匹配上 addOneTryCount(); @@ -215,7 +251,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - + ProMemory::getInstance().irisCam->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } diff --git a/utils/LogUtil.h b/utils/LogUtil.h new file mode 100644 index 0000000..eb4147c --- /dev/null +++ b/utils/LogUtil.h @@ -0,0 +1,87 @@ +#ifndef LOGUTIL_H +#define LOGUTIL_H + +#include "spdlog/spdlog.h" +#include "spdlog/sinks/daily_file_sink.h" + +#include "SettingConfig.h" + +// use embedded macro to support file and line number +#define LOG_TRACE(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::trace, __VA_ARGS__) +#define LOG_DEBUG(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::debug, __VA_ARGS__) +#define LOG_INFO(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::info, __VA_ARGS__) +#define LOG_WARN(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::warn, __VA_ARGS__) +#define LOG_ERROR(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::err, __VA_ARGS__) + + +class LogUtil +{ +public: + ~LogUtil() + { + spdlog::drop_all(); + } + + LogUtil(const LogUtil&)=delete; + LogUtil& operator=(const LogUtil&)=delete; //禁止生成默认赋值函数 + + // magic singleton static + static LogUtil* getInstance() { + static LogUtil instance; + return &instance; + } + + std::shared_ptr getLogger() + { + return m_logger; + } + +private: + LogUtil() + { + try { + + // Create a daily logger - a new file is created every day on 00:00am + m_logger = spdlog::daily_logger_mt("CasicIrisIdentify", SettingConfig::getInstance().LOG_FILE.toStdString(), 0, 0); + + m_logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e][%l] %v"); + + std::string level = SettingConfig::getInstance().LOG_LEVEL.toStdString(); + if (level == "trace") + { + m_logger->set_level(spdlog::level::trace); + m_logger->flush_on(spdlog::level::trace); + } + else if (level == "debug") + { + m_logger->set_level(spdlog::level::debug); + m_logger->flush_on(spdlog::level::debug); + } + else if (level == "info") + { + m_logger->set_level(spdlog::level::info); + m_logger->flush_on(spdlog::level::info); + } + else if (level == "warn") + { + m_logger->set_level(spdlog::level::warn); + m_logger->flush_on(spdlog::level::warn); + } + else if (level == "error") + { + m_logger->set_level(spdlog::level::err); + m_logger->flush_on(spdlog::level::err); + } + } + catch (const spdlog::spdlog_ex& ex) + { + spdlog::error("init log failed: {}",ex.what()); + + } + } + + std::shared_ptr m_logger; + +}; + +#endif // LOGUTIL_H diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp index 4b321c1..663db0f 100644 --- a/utils/SettingConfig.cpp +++ b/utils/SettingConfig.cpp @@ -12,6 +12,7 @@ WINDOW_TITLE = getProperty("window", "title").toString(); WINDOW_RIGHTS = getProperty("window", "copyright").toString(); WINDOW_VERSION = getProperty("window", "version").toString(); + DEVICE_CODE = getProperty("window", "deviceCode").toString(); IRIS_FRAME_WIDTH = getProperty("camera", "irisFrameWidth").toInt(); IRIS_FRAME_HEIGHT = getProperty("camera", "irisFrameHeight").toInt(); diff --git a/utils/SettingConfig.h b/utils/SettingConfig.h index 852b151..b65f553 100644 --- a/utils/SettingConfig.h +++ b/utils/SettingConfig.h @@ -32,6 +32,7 @@ QString WINDOW_TITLE; QString WINDOW_RIGHTS; QString WINDOW_VERSION; + QString DEVICE_CODE; int IRIS_FRAME_INTERVAL; int IRIS_FRAME_WIDTH; diff --git a/utils/UtilInclude.h b/utils/UtilInclude.h index b5e2ce9..0b329c9 100644 --- a/utils/UtilInclude.h +++ b/utils/UtilInclude.h @@ -4,7 +4,7 @@ #include #include "ByteUtil.h" #include "ImageUtil.h" -//#include "LogUtil.h" +#include "LogUtil.h" #include "SettingConfig.h" #include "SocketClientUtil.h" #include "SpeakerUtil.h" diff --git a/AppConstants.h b/AppConstants.h index dd1f6de..716094a 100644 --- a/AppConstants.h +++ b/AppConstants.h @@ -23,6 +23,13 @@ STATE_WORKING = 1, // 工作状态 STATE_IDENTIFYING = 2, // 识别中 }; + + enum IdentifyType + { + IRIS = 1, // 虹膜识别 + FACE = 2, // 人脸识别 + FINGER = 3, // 指纹识别 + }; }; #endif // APPCONSTANTS_H diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts deleted file mode 100644 index 81900df..0000000 --- a/CasicIrisIdentify_zh_CN.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdentifyForm - - - IdentifyForm - - - - diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp index 7fb3e7a..48dee69 100644 --- a/IdentifyForm.cpp +++ b/IdentifyForm.cpp @@ -37,7 +37,7 @@ void IdentifyForm::showRecogFailure() { -// SpeakerUtil::getInstance().speak("识别失败,请重试"); + SpeakerUtil::getInstance().speak("识别失败,请重试"); ui->wgtIdentifying->setCurrentIndex(2); @@ -50,54 +50,73 @@ ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; ui->labelIdenTips->setText(""); - CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } void IdentifyForm::showRecognizeResult(QString personId) { -// SpeakerUtil::getInstance().speak(QString("识别成功,项目部王珏%1").arg(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); // 查询并显示人员信息 -// SysPersonDao personDao; -// QVariantMap personInfo = personDao.findRecordById(personId); -// ui->labNameText->setText(""); -// ui->labNameText->setText(personInfo.value("name").toString()); -// ui->labGenderText->setText(""); -// ui->labGenderText->setText(CacheManager::getInstance().getGenderName().value(personInfo.value("gender").toString()).toString()); -// ui->labDeptText->setText(""); -// ui->labDeptText->setText(personInfo.value("deptname").toString()); -// ui->labTimeText->setText(""); -// ui->labTimeText->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + 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")); - ui->labelName->setText("王珏"); - ui->labelGender->setText("男"); - ui->labelDept->setText("项目部"); - ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")); - - QPixmap p; - p.load(":/images/photo.png"); - - float rp = p.width() * 1.0 / p.height() * 1.0; - float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; - - if (rp <= rl) { - p = p.scaledToHeight(ui->labelPhoto->height()); - } else { - p = p.scaledToWidth(ui->labelPhoto->width()); + // 查询并显示头像 + 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"); } - ui->labelPhoto->setPixmap(p); + // 缩放到合适的尺寸 + 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().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START; + + // 清除上一次识别的状态信息 + CasicIrisRecState::getInstance().restRecognize(); ui->wgtIdentifying->setCurrentIndex(0); }); } diff --git a/IdentifyForm.h b/IdentifyForm.h index d2f7931..f68954b 100644 --- a/IdentifyForm.h +++ b/IdentifyForm.h @@ -4,6 +4,9 @@ #include #include +#include "dao/SysPersonDao.h" +#include "dao/RecognitionRecordsDao.h" +#include "dao/util/CacheManager.h" #include "utils/UtilInclude.h" #include "ProMemory.h" @@ -29,6 +32,8 @@ private: Ui::IdentifyForm *ui; + SysPersonDao personDao; + RecognitionRecordsDao recordDao; }; #endif // IDENTIFYFORM_H diff --git a/LockScreenForm.ui b/LockScreenForm.ui index d7f40d1..64644b2 100644 --- a/LockScreenForm.ui +++ b/LockScreenForm.ui @@ -17,7 +17,7 @@ 0 - 300 + 270 600 100 @@ -33,7 +33,7 @@ 285 - 160 + 130 30 128 @@ -61,19 +61,13 @@ 0 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing @@ -83,19 +77,13 @@ 320 - 150 + 120 280 150 - - - Microsoft YaHei UI Light - 96 - - - 18 + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft @@ -105,7 +93,7 @@ 275 - 50 + 700 50 50 diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp index 9f07bfa..543d71c 100644 --- a/MainWindowForm.cpp +++ b/MainWindowForm.cpp @@ -40,6 +40,7 @@ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss")); ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd")); + ui->labelLogo->hide(); // 初始化更新界面的定时器 // 每秒执行一次 @@ -52,7 +53,7 @@ ProMemory::getInstance().irisCam->openIrisCamera(); connect(ProMemory::getInstance().irisCam->irisCamHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, identifyForm, &IdentifyForm::drawIrisImageOnFrame); -// LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); + LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString()); qDebug() << QString("应用程序启动成功[Application Startup Success]"); // 启动后显示视频画面 工作状态 未开始识别 @@ -89,6 +90,8 @@ 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); @@ -105,6 +108,7 @@ ui->labelMainTime->show(); ui->labelMainDate->show(); + ui->labelLogo->hide(); // 重新绑定每秒的定时信号和槽函数 disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime); diff --git a/MainWindowForm.ui b/MainWindowForm.ui index db44441..221a090 100644 --- a/MainWindowForm.ui +++ b/MainWindowForm.ui @@ -31,6 +31,9 @@ + + background: url(":images/bg_title.png") + @@ -60,6 +63,28 @@ Qt::AlignCenter + + + + 246 + 20 + 108 + 72 + + + + + + + images/logo.png + + + true + + + Qt::AlignCenter + + diff --git a/ProMemory.cpp b/ProMemory.cpp index f82aed4..18e4b3e 100644 --- a/ProMemory.cpp +++ b/ProMemory.cpp @@ -1,4 +1,8 @@ -#include "ProMemory.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ProMemory.h" ProMemory::ProMemory() { @@ -78,28 +82,57 @@ void ProMemory::initIrisFeatures() { + IrisDataDao irisDao; + /* CasicIrisFeature leftFeature; leftFeature.irisId = 1; - leftFeature.personId = "11"; + 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 = "11"; - rightFeature.irisCode = cv::imread("d:\\irisLogs\\photo\\165136-code.bmp", 0); - rightFeature.maskNorm = cv::imread("d:\\irisLogs\\photo\\165136-mask.bmp", 0); -*/ + 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); + 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) { + CasicIrisFeature featureLeft; + featureLeft.personId = iris.value("person_id").toString(); + featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray(); + + CasicIrisFeature featureRight; + featureRight.personId = iris.value("person_id").toString(); + featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray(); + + irisFeatures.append(featureLeft); + irisFeatures.append(featureRight); + } + + LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString()); } -/* -void ProMemory::initIrisFeatures(QString personId) -{ -// irisRegistPro->sendDataToExract(QByteArray(QString("[-u]").append(personId).toLocal8Bit())); -} -*/ QVector ProMemory::getIrisFeatures() { return this->irisFeatures; diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h index 3cc5773..e41ed26 100644 --- a/casic/iris/CasicIrisInfo.h +++ b/casic/iris/CasicIrisInfo.h @@ -12,7 +12,6 @@ // 眼部图像 // 后续计算需要使用 -// QImage data; cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图 cv::Mat maskNorm; diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp index 1558461..c528381 100644 --- a/casic/iris/CasicIrisInterface.cpp +++ b/casic/iris/CasicIrisInterface.cpp @@ -87,9 +87,6 @@ this->cascade->load(cascadeName); } - QElapsedTimer timer; - timer.start(); - std::vector rect; cv::Size minEyeRectSize(minEyeSize, minEyeSize); cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize); @@ -111,8 +108,8 @@ // .arg(timer.elapsed()).arg(rect.size()) // .arg(rect.at(0).x).arg(rect.at(0).y) // .arg(rect.at(0).width).arg(rect.at(0).height).toStdString()); - qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]") - .arg(timer.elapsed()).arg(rect.size()) + qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]") + .arg(rect.size()) .arg(rect.at(0).x).arg(rect.at(0).y) .arg(rect.at(0).width).arg(rect.at(0).height); @@ -141,20 +138,18 @@ } // 裁剪眼部图像 - cv::Mat halfSize = irisInfo.matData.clone(); - halfSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, + cv::Mat cutSize = irisInfo.matData.clone(); + cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5, center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5, SettingConfig::getInstance().IRIS_WIDTH * cutRatio, SettingConfig::getInstance().IRIS_HEIGHT * cutRatio)); - cv::resize(halfSize, halfSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); - cv::flip(halfSize, halfSize, 1); // 左右翻转 + // 裁剪后放大到 640 * 480 + cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT)); + cv::flip(cutSize, cutSize, 1); // 左右翻转 irisInfo.hasEye = true; -// irisInfo.eyeRect = rect.at(0); - - irisInfo.matData = halfSize; -// irisInfo.data = ImageUtil::MatImageToQImage(halfSize); + irisInfo.matData = cutSize; return irisInfo; } @@ -229,9 +224,18 @@ return irisInfo; } +QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo) +{ + QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm); + return irisFeatureCode; +} + float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo) { -// cv::imshow("info", irisInfo.irisCode); -// cv::waitKey(0); return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm); } + +float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other) +{ + return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data())); +} diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h index cbee8fe..26fbedc 100644 --- a/casic/iris/CasicIrisInterface.h +++ b/casic/iris/CasicIrisInterface.h @@ -27,7 +27,9 @@ CasicIrisInfo irisCodeExtract(CasicIrisInfo irisInfo); CasicIrisInfo irisEncode(CasicIrisInfo irisInfo); + QByteArray extractFeature(CasicIrisInfo irisInfo); float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo); + float calculatePairPoints(QByteArray feature, QByteArray other); void setCascadeFile(QString filename); void setMinEyeSize(int minEyeSize); diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp index c8ffe3e..ad456b4 100644 --- a/casic/iris/CasicIrisRec.cpp +++ b/casic/iris/CasicIrisRec.cpp @@ -177,6 +177,8 @@ // Get the coordinates file >> i; file >> j; + mvApplicationPoints.push_back(QPair(i, j)); + // Set pixel to "on" if (i < 0 || i > applicationPoints.rows - 1 || j < 0 || j > applicationPoints.cols- 1) { @@ -237,7 +239,96 @@ roi.copyTo(dst); //cv::copyTo(img2, dst, NULL); } - return encodeImage; + cv::Mat image8UC1; + encodeImage.convertTo(image8UC1, CV_8UC1); + return image8UC1; +} + +QByteArray CasicIrisRec::extractFeature(cv::Mat irisCode, cv::Mat maskNorm) +{ + // count points width and height + cv::Mat pointTemp(applicationPoints); + cv::Mat rowTemp; + + std::vector pointRows; + for (int i = 0; i < applicationPoints.rows; i++) { + rowTemp = pointTemp(cv::Rect(0, i, applicationPoints.cols, 1)); + if (cv::sum(rowTemp)[0] > 0) { + pointRows.push_back(i); + } + } + + int width = irisCode.cols; + int height = pointRows.size(); + rowTemp.release(); + pointTemp.release(); + + int n_codes = irisCode.rows / applicationPoints.rows; + + int irisDataLength = (n_codes + 1) * width * height; + uchar * irisData = new uchar[irisDataLength]; + int irisDataIndex = 0; + + uchar* codePixel = new uchar; + + // save iris code 512 * 8 * 6 + for (int n = 0; n < n_codes; n++) { // 6 + for (auto i : pointRows) { // 8 + i = n * maskNorm.rows + i; + for (int j = 0; j < irisCode.cols; j++) { // 512 + codePixel = (uchar*)(irisCode.data + i * irisCode.step + j); + if (*codePixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *codePixel; + } + } + } + } + + // save iris mask 512 * 8 * 1 + uchar * maskPixel; + for (auto i : pointRows) { // 8 + for (int j = 0; j < irisCode.cols; j++) { // 512 + maskPixel = (uchar*)(maskNorm.data + i * maskNorm.step + j); + if (*maskPixel == 255) { + irisData[irisDataIndex++] = 1; + } + else { + irisData[irisDataIndex++] = *maskPixel; + } + } + } + + + uchar * irisFeaturePtr = new uchar[irisDataLength / 8 + 5]; + memset(irisFeaturePtr, 0, irisDataLength / 8 + 5); + + // first byte is width; + irisFeaturePtr[0] = (uchar)width; + irisFeaturePtr[1] = (uchar)(width >> 8); + + // second byte is height; + irisFeaturePtr[2] = (uchar)height; + + // third byte is n_codes + irisFeaturePtr[3] = (uchar)n_codes; + + // fourth byte is n_mask(1) + irisFeaturePtr[4] = (uchar)1; + for (int i = 0; i < irisDataLength; i++) { + irisFeaturePtr[5 + i / 8] += irisData[i] << (7 - (i % 8)); + } + + QByteArray feature; + for (int i = 0; i < irisDataLength / 8 + 5; i++) { + feature.append((char) irisFeaturePtr[i]); + } + + delete[] irisData; + delete[] irisFeaturePtr; + return feature; } float CasicIrisRec::matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2) @@ -283,6 +374,67 @@ } +float CasicIrisRec::matchFeatureCode(uchar *feature1, uchar *feature2) +{ + int width = feature1[0] | feature1[1] << 8; // 32 + int height = feature1[2]; // 8 + int nCode = feature1[3]; // 6 +// int nMask = feature1[4]; + + uchar ** irisData1 = reduceIrisCode(feature1); + uchar ** irisMask1 = reduceIrisMask(feature1); + uchar ** irisData2 = reduceIrisCode(feature2); + uchar ** irisMask2 = reduceIrisMask(feature2); + + int shift = 10; + float score = 1.0; + + int minstep = 0 - shift; + int maxstep = shift; + + for (int s = minstep; s <= maxstep; s++) { + int count = 0; + float mean = 0.0; + for (int n = 0; n < nCode; n++) { + for (auto pos : mvApplicationPoints) { + int row = pos.first / mvApplicationPoints[0].first - 1; + int col = (pos.second + s + width) % width; + + if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) { + + uchar tmp1 = irisData1[row + height * n][col]; + uchar tmp2 = irisData2[row + height * n][pos.second]; + mean += tmp1 ^ tmp2; + count += 1; + } + } + } + + //cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << endl; + mean = mean / count; + score = mean < score ? mean : score; + + } + +// std::cout << "feature score: " << score << std::endl; + + +// for (int i = 0; i < height * nCode; i++) { +// delete irisData1[i]; +// delete irisData2[i]; +// } +// delete irisData1; +// delete irisData2; + +// for (int i = 0; i < height; i++) { +// delete irisMask1[i]; +// delete irisMask2[i]; +// } +// delete irisMask1; +// delete irisMask2; + return score; +} + cv::Mat CasicIrisRec::addBorders(cv::Mat pSrc, int width) { cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels()); @@ -298,4 +450,39 @@ return result; } +uchar ** CasicIrisRec::reduceIrisCode(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2] * feature[3]; + + uchar ** reduceCode = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + reduceCode[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = i * width + j; + reduceCode[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return reduceCode; +} + +uchar ** CasicIrisRec::reduceIrisMask(uchar *feature) +{ + int width = feature[0] | feature[1] << 8; + int height = feature[2]; // 8 + int nCode = feature[3]; // 6 + + uchar ** irisMask = new uchar*[width*height]; + for (int i = 0; i < height; i++) { + irisMask[i] = new uchar[width]; + for (int j = 0; j < width; j++) { + int tmp = width * height * nCode + i * width + j; + irisMask[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1; + } + } + + return irisMask; +} + } diff --git a/casic/iris/CasicIrisRec.h b/casic/iris/CasicIrisRec.h index f6ca8ac..2d9616e 100644 --- a/casic/iris/CasicIrisRec.h +++ b/casic/iris/CasicIrisRec.h @@ -5,6 +5,8 @@ #define NORM_HEIGHT 64 #define M_PI 3.1415926535897323846 +#include +#include #include namespace iristrt @@ -15,28 +17,28 @@ public: CasicIrisRec(); - CasicIrisRec(const char * gaborFilterFileName,const char * applicationPointsFileName); - ~CasicIrisRec(); cv::Mat normalize(cv::Mat image, int iris_x, int iris_y, int iris_r,int pupil_x, int pupil_y, int pupil_r); - cv::Mat encodeToImage(cv::Mat normalizedImage); + QByteArray extractFeature(cv::Mat irisCode, cv::Mat maskNorm); float matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2); + float matchFeatureCode(uchar * feature1, uchar * feature2); private: std::vector gaborFilters; - cv::Mat applicationPoints; + std::vector> mvApplicationPoints; std::vector loadGaborFilters(const char * gaborFilterFileName); - cv::Mat loadApplicationPoints(const char * applicationPointsFileName); cv::Mat addBorders(cv::Mat pSrc, int width); + uchar ** reduceIrisCode(uchar * feature); + uchar ** reduceIrisMask(uchar * feature); }; // end of class CasicIrisRec diff --git a/dao/IrisDataDao.cpp b/dao/IrisDataDao.cpp index 37a0ed6..63eda4d 100644 --- a/dao/IrisDataDao.cpp +++ b/dao/IrisDataDao.cpp @@ -1,3 +1,7 @@ +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + #include "IrisDataDao.h" IrisDataDao::IrisDataDao(QObject *parent) : BaseDao(parent) @@ -37,7 +41,7 @@ result.append(item); } -// LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); + LOG_DEBUG(QString("查询IRIS_DATA表的所有记录[结果数:%1]").arg(result.size()).toStdString()); return result; } @@ -104,7 +108,7 @@ result.insert("right_iris_code3", query.value("right_iris_code3")); } -// LOG_DEBUG(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); + LOG_TRACE(QString("根据personId查询IRIS_DATA表的记录[personId=%1]").arg(personId).toStdString()); return result; } @@ -114,7 +118,12 @@ // 新建查询 QSqlQuery query(ConnectionManager::getInstance()->getConnection()); - qulonglong id = ConnectionManager::getInstance()->generateId(); + qulonglong id; + if (object.contains("id") == true) { + id = object.value("id").toULongLong(); + } else { + id = ConnectionManager::getInstance()->generateId(); + } // INSERT语句 QString sql = QString("INSERT INTO IRIS_DATA (ID, PERSON_ID, ID_CARD_NO, LEFT_IRIS_CODE1, RIGHT_IRIS_CODE1) VALUES (:id, :personId, :idCardNo, :left1, :right1)"); @@ -132,7 +141,7 @@ // 执行插入 bool success = query.exec(); -// LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); + LOG_DEBUG(QString("保存虹膜特征值[%1][id=%2]").arg(success).arg(id).toStdString()); // 结束事务 ConnectionManager::getInstance()->getConnection().commit(); diff --git a/dao/RecognitionRecordsDao.cpp b/dao/RecognitionRecordsDao.cpp index 40db453..d795039 100644 --- a/dao/RecognitionRecordsDao.cpp +++ b/dao/RecognitionRecordsDao.cpp @@ -1,4 +1,4 @@ -#include "RecognitionRecordsDao.h" +#include "RecognitionRecordsDao.h" RecognitionRecordsDao::RecognitionRecordsDao(QObject *parent) : BaseDao(parent) { @@ -58,10 +58,8 @@ query.bindValue(":doorCode", object.value("door_code").toString()); query.bindValue(":inoutType", object.value("inout_type").toString()); -// LOG_DEBUG(sql.toStdString()); - // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES (:id, :logInfo)"); + QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES (:id, :logInfo)"); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/dao/SysDictDao.cpp b/dao/SysDictDao.cpp new file mode 100644 index 0000000..7a2bc8b --- /dev/null +++ b/dao/SysDictDao.cpp @@ -0,0 +1,82 @@ +#include "SysDictDao.h" + + +SysDictDao::SysDictDao(QObject *parent) : BaseDao(parent) +{ + +} + +QVector SysDictDao::findAllRecord() +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT"; + + // 执行查询 + query.exec(sql); + + // 返回结果 + QVector result; + + // 遍历查询结果 + while (query.next()) { + QVariantMap item; + + item.insert("id", query.value("id").toLongLong()); + item.insert("code", query.value("code").toString()); + item.insert("name", query.value("name").toString()); + item.insert("pid", query.value("pid").toString()); + + result.append(item); + } + + return result; +} + +QVariantMap SysDictDao::findRecordById(QString id) +{ + QVariantMap item; + return item; +} + + +QVariantMap SysDictDao::findChildDictByCode(QString code) +{ + // 新建查询 + QSqlQuery query(ConnectionManager::getInstance()->getConnection()); + + // 查询语句 + QString sql = "SELECT * FROM SYS_DICT where PID = (SELECT ID FROM SYS_DICT WHERE CODE = :code)"; + query.prepare(sql); + query.bindValue(":code", code); + + // 执行查询 + query.exec(); + + // 返回结果 + QVariantMap result; + + // 遍历查询结果 + while (query.next()) { + result.insert(query.value("code").toString(), query.value("name").toString()); + } + + return result; +} + +QString SysDictDao::save(QVariantMap object) +{ + return "0"; +} + +bool SysDictDao::edit(QVariantMap newObject, QString id) +{ + return false; +} + +bool SysDictDao::dele(QString id) +{ + return false; +} diff --git a/dao/SysDictDao.h b/dao/SysDictDao.h new file mode 100644 index 0000000..7c73aff --- /dev/null +++ b/dao/SysDictDao.h @@ -0,0 +1,23 @@ +#ifndef SYSDICTDAO_H +#define SYSDICTDAO_H + +#include +#include "BaseDao.h" + +class SysDictDao : public BaseDao +{ + Q_OBJECT +public: + explicit SysDictDao(QObject *parent = nullptr); + + QVector findAllRecord(); + QVariantMap findRecordById(QString id); + + QVariantMap findChildDictByCode(QString code); + + QString save(QVariantMap object); + bool edit(QVariantMap newObject, QString id); + bool dele(QString id); +}; + +#endif // SYSDICTDAO_H diff --git a/dao/SysPersonDao.cpp b/dao/SysPersonDao.cpp index dd9480f..19243b1 100644 --- a/dao/SysPersonDao.cpp +++ b/dao/SysPersonDao.cpp @@ -1,4 +1,4 @@ -#include "SysPersonDao.h" +#include "SysPersonDao.h" SysPersonDao::SysPersonDao(QObject *parent) : BaseDao(parent) @@ -56,10 +56,13 @@ QSqlQuery query(ConnectionManager::getInstance()->getConnection()); // 查询语句 - QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = '%1'").arg(id); + QString sql = QString("SELECT * FROM SYS_PERSON LEFT JOIN SYS_DEPT ON SYS_PERSON.DEPTID = SYS_DEPT.ID WHERE SYS_PERSON.DELFLAG = '0' AND SYS_PERSON.ID = :id"); + + query.prepare(sql); + query.bindValue(":id", id); // 执行查询 - query.exec(sql); + query.exec(); // 返回结果 QVariantMap result; @@ -84,8 +87,9 @@ result.insert("person_code", query.value("person_code").toString()); result.insert("deptname", query.value("fullname").toString()); result.insert("sync_id", query.value("sync_id").toString()); - result.insert("hasFace", query.value("face_valid").toString()); - result.insert("hasIris", query.value("iris_valid").toString()); + result.insert("avatar", query.value("avatar").toString()); +// result.insert("hasFace", query.value("face_valid").toString()); +// result.insert("hasIris", query.value("iris_valid").toString()); } // LOG(TRACE) << QString("根据id查询SYS_PERSON表的记录[id=%1][%2]").arg(id).arg(sql).toStdString(); diff --git a/dao/dao.pri b/dao/dao.pri index 1e04ce4..5f3b7f3 100644 --- a/dao/dao.pri +++ b/dao/dao.pri @@ -4,15 +4,17 @@ HEADERS += $$PWD/RecognitionRecordsDao.h HEADERS += $$PWD/SysPersonDao.h HEADERS += $$PWD/SysDeptDao.h +HEADERS += $$PWD/SysDictDao.h SOURCES += $$PWD/BaseDao.cpp SOURCES += $$PWD/IrisDataDao.cpp SOURCES += $$PWD/RecognitionRecordsDao.cpp SOURCES += $$PWD/SysPersonDao.cpp SOURCES += $$PWD/SysDeptDao.cpp +SOURCES += $$PWD/SysDictDao.cpp HEADERS += $$PWD/util/ConnectionManager.h SOURCES += $$PWD/util/ConnectionManager.cpp -#HEADERS += $$PWD/util/CacheManager.h -#SOURCES += $$PWD/util/CacheManager.cpp +HEADERS += $$PWD/util/CacheManager.h +SOURCES += $$PWD/util/CacheManager.cpp diff --git a/dao/util/CacheManager.cpp b/dao/util/CacheManager.cpp new file mode 100644 index 0000000..e415d93 --- /dev/null +++ b/dao/util/CacheManager.cpp @@ -0,0 +1,12 @@ +#include "CacheManager.h" + +CacheManager::CacheManager() +{ + SysDictDao dictDao; + genderName = dictDao.findChildDictByCode("gender"); +} + +QVariantMap CacheManager::getGenderName() +{ + return genderName; +} diff --git a/dao/util/CacheManager.h b/dao/util/CacheManager.h new file mode 100644 index 0000000..5226744 --- /dev/null +++ b/dao/util/CacheManager.h @@ -0,0 +1,31 @@ +#ifndef CACHEMANAGER_H +#define CACHEMANAGER_H + +#include +#include +#include "dao/SysDeptDao.h" +#include "dao/SysDictDao.h" +#include "dao/SysPersonDao.h" +#include "dao/IrisDataDao.h" + +class CacheManager +{ +public: + ~CacheManager() {}; + CacheManager(const CacheManager&)=delete; + CacheManager& operator=(const CacheManager&)=delete; + + static CacheManager& getInstance() { + static CacheManager instance; + return instance; + } + + QVariantMap getGenderName(); + +private: + CacheManager(); + + QVariantMap genderName; +}; + +#endif // CACHEMANAGER_H diff --git a/dao/util/ConnectionManager.cpp b/dao/util/ConnectionManager.cpp index 84b17be..fed7b8d 100644 --- a/dao/util/ConnectionManager.cpp +++ b/dao/util/ConnectionManager.cpp @@ -1,4 +1,8 @@ -#include "ConnectionManager.h" +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) +#endif + +#include "ConnectionManager.h" #include Q_GLOBAL_STATIC(ConnectionManager, cm) @@ -18,10 +22,10 @@ bool succ = conn.open(); if (succ == true) { -// LOG_INFO(QString("打开数据库操作正常[Open Database Success]").toStdString()); + LOG_INFO(QString("打开数据库操作正常[Open Database Success]").toStdString()); } else { -// LOG_ERROR(QString("打开数据库操作失败[Open Database Failed]").toStdString()); + LOG_ERROR(QString("打开数据库操作失败[Open Database Failed]").toStdString()); } } } diff --git a/device/iris/CasicIrisRecState.cpp b/device/iris/CasicIrisRecState.cpp index 41105e1..c5e5f13 100644 --- a/device/iris/CasicIrisRecState.cpp +++ b/device/iris/CasicIrisRecState.cpp @@ -25,15 +25,43 @@ QDateTime now = QDateTime::currentDateTime(); this->recoginzeId = now.toString("yyyyMMddHHmmsszzz"); this->timeStamp = now.toMSecsSinceEpoch(); + this->timeStampSucc = 0; + this->tryCount = 0; this->noEyeCount = 0; + this->matchedId = ""; -// LOG(DEBUG) << QString("[CasicIrisRecState][initRecognize] 虹膜识别状态初始化").toStdString(); -// LOG_DEBUG(QString("[CasicIrisRecState][initRecognize] 虹膜识别状态初始化").toStdString()); + this->findEyeTmLast = 0; + this->segmentTmLast = 0; + this->extractTmLast = 0; + this->matchTmLast = 0; + this->recogTimeLast = 0; + + LOG_INFO(QString("[initRecognize][%1] 虹膜识别状态初始化").arg(recoginzeId).toStdString()); qDebug() << QString("[CasicIrisRecState][initRecognize][%1] 虹膜识别状态初始化").arg(recoginzeId); } +void CasicIrisRecState::restRecognize() +{ + this->recoginzeId = ""; + this->timeStamp = 0; + this->timeStampSucc = 0; + + this->tryCount = 0; + this->noEyeCount = 0; + + this->matchedId = ""; + this->score = 0.0f; + this->state = IrisRecStateName::REC_NOT_START; + + this->findEyeTmLast = 0; + this->segmentTmLast = 0; + this->extractTmLast = 0; + this->matchTmLast = 0; + this->recogTimeLast = 0; +} + QString CasicIrisRecState::toString() { return QString(QJsonDocument(toJSON()).toJson(QJsonDocument::Compact)); @@ -47,13 +75,19 @@ obj.insert("recoginzeId", recoginzeId); obj.insert("timestamp", timeStamp); obj.insert("timestampSucc", timeStampSucc); + obj.insert("state", state); + obj.insert("matchedId", matchedId); + obj.insert("score", score); + obj.insert("tryCount", tryCount); obj.insert("noEyeCount", noEyeCount); - obj.insert("recogTimeLast", recogTimeLast); - QJsonObject eyeObj; - eyeObj.insert("hasEye", irisInfo->hasEye); + obj.insert("recogTimeLast", recogTimeLast); + obj.insert("findEyeTmLast", findEyeTmLast); + obj.insert("segmentTmLast", segmentTmLast); + obj.insert("extractTmLast", extractTmLast); + obj.insert("matchTmLast", matchTmLast); return obj; } diff --git a/device/iris/CasicIrisRecState.h b/device/iris/CasicIrisRecState.h index 7506581..e978d58 100644 --- a/device/iris/CasicIrisRecState.h +++ b/device/iris/CasicIrisRecState.h @@ -22,6 +22,7 @@ } void initRecognize(); + void restRecognize(); QString toString(); QJsonObject toJSON(); @@ -29,6 +30,11 @@ qint64 timeStamp = 0; // 识别开始时间戳 qint64 timeStampSucc = 0; // 识别成功时的时间戳 qint64 findEyeTmLast = 0; // 找眼操作耗时 + qint64 segmentTmLast = 0; // 图像分割操作耗时 + qint64 extractTmLast = 0; // 编码操作耗时 + qint64 matchTmLast = 0; // 匹配操作耗时 + + float score = 0.0f; // 匹配评分 CasicIrisInfo * irisInfo; @@ -36,7 +42,7 @@ qint8 tryCount = 0; // 识别尝试次数 qint16 noEyeCount = 0; // 连续没有找到眼睛次数 - float recogTimeLast = 0.0; // 识别成功耗时 + qint16 recogTimeLast = 0.0; // 识别成功耗时ms /** * @brief state @@ -53,8 +59,6 @@ enum IrisRecStateName { REC_NOT_START = 0, // 未开始 - REC_LEFT_FIND_EYE = 1, // 检测左眼, 没找到右眼 - REC_RIGHT_FIND_EYE = 2, // 检测右眼, 没找到左眼 REC_FIND_EYE = 3, // 找到左眼和右眼 REC_FEATURE_EXTRACT = 4, // 特征值提取成功 REC_SEARCH_SUCC = 5, // 虹膜库比对成功 diff --git a/device/iris/IrisRecogProcess.cpp b/device/iris/IrisRecogProcess.cpp index 5ca377e..38f54fe 100644 --- a/device/iris/IrisRecogProcess.cpp +++ b/device/iris/IrisRecogProcess.cpp @@ -62,10 +62,20 @@ // 3. 取出虹膜图像栈中的一条数据 CasicIrisInfo irisInfo = ProMemory::getInstance().popCasicIris(); - // 4. 调用找眼分类器算法 + QElapsedTimer timer; + timer.start(); + + // 4. 调用找眼分类器算法 第一阶段 casic::iris::CasicIrisInterface::getInstance().setMinEyeSize(SettingConfig::getInstance().MIN_EYE_SIZE); irisInfo = casic::iris::CasicIrisInterface::getInstance().findAndCutEye(irisInfo); + // 找眼计时 + int findEyeLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 找眼及裁剪[%1 ms]").arg(findEyeLast); + +// irisInfo.matData = cv::imread("d:\\irisLogs\\photo\\right.bmp", 0); +// irisInfo.hasEye = true; + // 4.1 没有找到眼睛则返回 if (irisInfo.hasEye == false) { @@ -77,13 +87,13 @@ continue; } - // 4.2 找到眼睛则开始识别 + // 5. 找到眼睛则开始识别 // 发送信号更新界面 emit startIdentifyIris(); // 调用远程算法进行编码 - if (CasicIrisRecState::getInstance().recoginzeId == "0") + if (CasicIrisRecState::getInstance().recoginzeId == "0" || CasicIrisRecState::getInstance().recoginzeId == "") { // 第一次找到眼则 虹膜识别状态初始化 CasicIrisRecState::getInstance().initRecognize(); @@ -92,10 +102,14 @@ CasicIrisRecState::getInstance().noEyeCount = 0; // 持续未找到眼的次数清零 CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FIND_EYE; - QElapsedTimer timer; - timer.start(); + LOG_DEBUG(QString("[IrisRecogProcess step.1] 找眼及裁剪成功[%1 ms]").arg(findEyeLast).toStdString()); + CasicIrisRecState::getInstance().findEyeTmLast = findEyeLast; + CasicIrisRecState::getInstance().recogTimeLast += findEyeLast; - // 进行预处理 转换成 320 * 240 的三通道图像 送去压缩 + // 6. 分割图像 + timer.restart(); + + // 进行预处理 转换成 320 * 240 的三通道图像 送去分割 cv::Mat segMat; // 图像转换为RGB的彩色图像 @@ -108,7 +122,8 @@ // cv::imwrite(filename, segMat); // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); - QByteArray data((char*)segMat.data, SettingConfig::getInstance().IRIS_WIDTH * 0.5 * SettingConfig::getInstance().IRIS_HEIGHT * 0.5 * 3); + int segMatSize = segMat.cols * segMat.rows; + QByteArray data((char*)segMat.data, segMatSize * 3); // 三通道 // 发送TCP消息去匹配 emit sendDataToExract(data); @@ -131,27 +146,27 @@ char recvMask[320 * 240 * 1]; char recvIris[320 * 240 * 1]; memset(recvPupil, 0, sizeof(recvPupil)); - memset(recvMask, 0, sizeof(recvMask)); - memset(recvIris, 0, sizeof(recvIris)); + memset(recvMask, 0, sizeof (recvMask)); + memset(recvIris, 0, sizeof (recvIris)); for (int i = 0; i < clientUtil->getResponse().size(); i++) { - if (i < 320 * 240) + if (i < segMatSize) recvPupil[i] = clientUtil->getResponse().at(i); - else if (i >= 320 * 240 && i < 2 * 320 * 240) - recvMask[i - 320 * 240] = clientUtil->getResponse().at(i); + else if (i >= segMatSize && i < 2 * segMatSize) + recvMask[i - segMatSize] = clientUtil->getResponse().at(i); else - recvIris[i - 2 * 320 * 240] = clientUtil->getResponse().at(i); + recvIris[i - 2 * segMatSize] = clientUtil->getResponse().at(i); } - // 成功接收后清除缓存区 - clientUtil->resetRecvBuffer(); - - cv::Mat pupil(240, 320, CV_8UC1, recvPupil); - cv::Mat mask(240, 320, CV_8UC1, recvMask); - cv::Mat iris(240, 320, CV_8UC1, recvIris); + cv::Mat pupil(segMat.rows, segMat.cols, CV_8UC1, recvPupil); + cv::Mat mask(segMat.rows, segMat.cols, CV_8UC1, recvMask); + cv::Mat iris(segMat.rows, segMat.cols, CV_8UC1, recvIris); irisInfo.segResult.innerMask = pupil; irisInfo.segResult.irisMask = mask; irisInfo.segResult.outerCircle = iris; - /* + + // 成功接收后清除缓存区 + 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(); @@ -159,9 +174,15 @@ cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); */ - qDebug() << QString("算法分割图像成功[%1 ms]").arg(timer.elapsed()); + // 第二阶段 分割图像计时 + int segLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 算法分割图像成功[%1 ms]").arg(segLast); + LOG_DEBUG(QString("[IrisRecogProcess step.2] 算法分割图像成功[%1 ms]").arg(segLast).toStdString()); + CasicIrisRecState::getInstance().segmentTmLast = segLast; + CasicIrisRecState::getInstance().recogTimeLast += segLast; - // 分割后的后处理 + // 7. 分割后的后处理 编码及提取特征值 + timer.restart(); if (cv::countNonZero(mask) == 0 || cv::countNonZero(pupil) == 0|| cv::countNonZero(iris) == 0) { qDebug() << "算法分割图像失败,暂停200ms"; @@ -173,38 +194,53 @@ // 状态修改为特征提取 CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; - - timer.restart(); 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")).toStdString(); - std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); +/* + 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(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); +*/ - qDebug() << QString("虹膜图像编码成功[%1 ms]").arg(timer.elapsed()); + // 从编码中提取特征值 + irisInfo.irisFeatureCode = casic::iris::CasicIrisInterface::getInstance().extractFeature(irisInfo); + + int encodeLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 虹膜图像编码并提取特征值成功[%1 ms]").arg(encodeLast); + LOG_DEBUG(QString("[IrisRecogProcess step.3] 虹膜图像编码并提取特征值成功[%1 ms]").arg(encodeLast).toStdString()); + CasicIrisRecState::getInstance().extractTmLast = encodeLast; + CasicIrisRecState::getInstance().recogTimeLast += encodeLast; // 开始匹配 + timer.restart(); for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) { CasicIrisFeature feature = ProMemory::getInstance().getIrisFeatures().at(i); - float score = casic::iris::CasicIrisInterface::getInstance().calculateMatchScore(feature, irisInfo); - // SpeakerUtil::getInstance().speak(QString::number(score)); - cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).arg(score).toStdString(), irisInfo.matData); + + 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); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; + CasicIrisRecState::getInstance().score = score; + CasicIrisRecState::getInstance().timeStampSucc = QDateTime::currentMSecsSinceEpoch(); + break ; } } + int matchLast = timer.elapsed(); + qDebug() << QString("[IrisRecogProcess] 虹膜库匹配[%1 ms][%2]").arg(matchLast).arg(CasicIrisRecState::getInstance().state); + LOG_DEBUG(QString("[IrisRecogProcess step.4] 虹膜库匹配[%1 ms][%2]").arg(matchLast).arg(CasicIrisRecState::getInstance().state).toStdString()); + CasicIrisRecState::getInstance().matchTmLast = matchLast; + CasicIrisRecState::getInstance().recogTimeLast += matchLast; + if (CasicIrisRecState::getInstance().state == CasicIrisRecState::REC_SEARCH_SUCC) { // 找到匹配结果 - emit findMatchedIris(CasicIrisRecState::getInstance().matchedId); + afterRecogAction(); - ProMemory::getInstance().irisCam->stopCapture(); - ProMemory::getInstance().clearIrisQueue(); - this->setWorking(false); + emit findMatchedIris(CasicIrisRecState::getInstance().matchedId); } else { // 没有匹配上 addOneTryCount(); @@ -215,7 +251,7 @@ void IrisRecogProcess::afterRecogAction() { this->setWorking(false); - + ProMemory::getInstance().irisCam->stopCapture(); ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈 } diff --git a/utils/LogUtil.h b/utils/LogUtil.h new file mode 100644 index 0000000..eb4147c --- /dev/null +++ b/utils/LogUtil.h @@ -0,0 +1,87 @@ +#ifndef LOGUTIL_H +#define LOGUTIL_H + +#include "spdlog/spdlog.h" +#include "spdlog/sinks/daily_file_sink.h" + +#include "SettingConfig.h" + +// use embedded macro to support file and line number +#define LOG_TRACE(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::trace, __VA_ARGS__) +#define LOG_DEBUG(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::debug, __VA_ARGS__) +#define LOG_INFO(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::info, __VA_ARGS__) +#define LOG_WARN(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::warn, __VA_ARGS__) +#define LOG_ERROR(...) SPDLOG_LOGGER_CALL(LogUtil::getInstance()->getLogger().get(), spdlog::level::err, __VA_ARGS__) + + +class LogUtil +{ +public: + ~LogUtil() + { + spdlog::drop_all(); + } + + LogUtil(const LogUtil&)=delete; + LogUtil& operator=(const LogUtil&)=delete; //禁止生成默认赋值函数 + + // magic singleton static + static LogUtil* getInstance() { + static LogUtil instance; + return &instance; + } + + std::shared_ptr getLogger() + { + return m_logger; + } + +private: + LogUtil() + { + try { + + // Create a daily logger - a new file is created every day on 00:00am + m_logger = spdlog::daily_logger_mt("CasicIrisIdentify", SettingConfig::getInstance().LOG_FILE.toStdString(), 0, 0); + + m_logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e][%l] %v"); + + std::string level = SettingConfig::getInstance().LOG_LEVEL.toStdString(); + if (level == "trace") + { + m_logger->set_level(spdlog::level::trace); + m_logger->flush_on(spdlog::level::trace); + } + else if (level == "debug") + { + m_logger->set_level(spdlog::level::debug); + m_logger->flush_on(spdlog::level::debug); + } + else if (level == "info") + { + m_logger->set_level(spdlog::level::info); + m_logger->flush_on(spdlog::level::info); + } + else if (level == "warn") + { + m_logger->set_level(spdlog::level::warn); + m_logger->flush_on(spdlog::level::warn); + } + else if (level == "error") + { + m_logger->set_level(spdlog::level::err); + m_logger->flush_on(spdlog::level::err); + } + } + catch (const spdlog::spdlog_ex& ex) + { + spdlog::error("init log failed: {}",ex.what()); + + } + } + + std::shared_ptr m_logger; + +}; + +#endif // LOGUTIL_H diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp index 4b321c1..663db0f 100644 --- a/utils/SettingConfig.cpp +++ b/utils/SettingConfig.cpp @@ -12,6 +12,7 @@ WINDOW_TITLE = getProperty("window", "title").toString(); WINDOW_RIGHTS = getProperty("window", "copyright").toString(); WINDOW_VERSION = getProperty("window", "version").toString(); + DEVICE_CODE = getProperty("window", "deviceCode").toString(); IRIS_FRAME_WIDTH = getProperty("camera", "irisFrameWidth").toInt(); IRIS_FRAME_HEIGHT = getProperty("camera", "irisFrameHeight").toInt(); diff --git a/utils/SettingConfig.h b/utils/SettingConfig.h index 852b151..b65f553 100644 --- a/utils/SettingConfig.h +++ b/utils/SettingConfig.h @@ -32,6 +32,7 @@ QString WINDOW_TITLE; QString WINDOW_RIGHTS; QString WINDOW_VERSION; + QString DEVICE_CODE; int IRIS_FRAME_INTERVAL; int IRIS_FRAME_WIDTH; diff --git a/utils/UtilInclude.h b/utils/UtilInclude.h index b5e2ce9..0b329c9 100644 --- a/utils/UtilInclude.h +++ b/utils/UtilInclude.h @@ -4,7 +4,7 @@ #include #include "ByteUtil.h" #include "ImageUtil.h" -//#include "LogUtil.h" +#include "LogUtil.h" #include "SettingConfig.h" #include "SocketClientUtil.h" #include "SpeakerUtil.h" diff --git a/utils/utils.pri b/utils/utils.pri index f72ccb5..39294b1 100644 --- a/utils/utils.pri +++ b/utils/utils.pri @@ -9,7 +9,7 @@ HEADERS += $$PWD/ImageUtil.h SOURCES += $$PWD/ImageUtil.cpp -#HEADERS += $$PWD/LogUtil.h +HEADERS += $$PWD/LogUtil.h HEADERS += $$PWD/SettingConfig.h SOURCES += $$PWD/SettingConfig.cpp @@ -23,12 +23,6 @@ HEADERS += $$PWD/SocketClientUtil.h SOURCES += $$PWD/SocketClientUtil.cpp -#HEADERS += $$PWD/SelectDeptUtil.h -#SOURCES += $$PWD/SelectDeptUtil.cpp - HEADERS += $$PWD/ByteUtil.h -#HEADERS += $$PWD/TimerCounter.h - SOURCES += $$PWD/ByteUtil.cpp -#SOURCES += $$PWD/TimerCounter.cpp