diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp index f202cfe..bc8018b 100644 --- a/CasicBioRecWin.cpp +++ b/CasicBioRecWin.cpp @@ -6,7 +6,7 @@ , ui(new Ui::CasicBioRecWin) { // 打开外部可执行程序 - outExe = new QProcess(this); +// outExe = new QProcess(this); // outExe->start(SettingConfig::getInstance().OUT_EXE_FILE); ui->setupUi(this); @@ -31,6 +31,7 @@ initFaceRecogThread(); // 人脸识别线程 initIrisRegistThread(); // 虹膜注册线程 initIrisRecogThread(); // 虹膜识别线程 + initCameraPositionThread(); // 调整相机位置 // 初始化人脸相机控制 ProMemory::getInstance().faceCam = new FaceCameraController(this); @@ -49,6 +50,12 @@ connect(ProMemory::getInstance().irisCam->rightHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, addPersonForm, &AddPersonForm::drawIrisImageOnFrame); + // 初始化电机控制 + ProMemory::getInstance().moto = new MotoController(this); + ProMemory::getInstance().moto->initSerialMCU(); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::motoControl, + ProMemory::getInstance().moto, &MotoController::autoPosition); + // 打印日志 LOG(INFO) << QString("应用程序启动成功[Application Startup Success]").toStdString(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::MAIN_PAGE; @@ -72,6 +79,10 @@ ProMemory::getInstance().irisRecogPro->deleteLater(); ProMemory::getInstance().irisRecogPro->wait(); + ProMemory::getInstance().camPosCtrl->exitThread(); + ProMemory::getInstance().camPosCtrl->deleteLater(); + ProMemory::getInstance().camPosCtrl->wait(); + // 关闭自动启动的外部程序 // outExe->close(); // delete outExe; @@ -81,12 +92,14 @@ delete ProMemory::getInstance().faceRecogPro; delete ProMemory::getInstance().irisRegistPro; delete ProMemory::getInstance().irisRecogPro; + delete ProMemory::getInstance().camPosCtrl; } void CasicBioRecWin::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: + LOG(INFO) << "" << std::endl; QTimer::singleShot(100, qApp, SLOT(quit())); default: @@ -204,8 +217,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -244,8 +255,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -255,3 +264,17 @@ ProMemory::getInstance().irisRecogPro->start(); } + +void CasicBioRecWin::initCameraPositionThread() +{ + // 调整相机位置处理 + ProMemory::getInstance().camPosCtrl = new CameraPositionController(this); + + // 绑定信号与槽函数 + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTips, + recogResultForm, &RecognizeResultForm::updateRecogTips); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTipsBackgroundColor, + recogResultForm, &RecognizeResultForm::updateRecogTipsColor); + + ProMemory::getInstance().camPosCtrl->start(); +} diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp index f202cfe..bc8018b 100644 --- a/CasicBioRecWin.cpp +++ b/CasicBioRecWin.cpp @@ -6,7 +6,7 @@ , ui(new Ui::CasicBioRecWin) { // 打开外部可执行程序 - outExe = new QProcess(this); +// outExe = new QProcess(this); // outExe->start(SettingConfig::getInstance().OUT_EXE_FILE); ui->setupUi(this); @@ -31,6 +31,7 @@ initFaceRecogThread(); // 人脸识别线程 initIrisRegistThread(); // 虹膜注册线程 initIrisRecogThread(); // 虹膜识别线程 + initCameraPositionThread(); // 调整相机位置 // 初始化人脸相机控制 ProMemory::getInstance().faceCam = new FaceCameraController(this); @@ -49,6 +50,12 @@ connect(ProMemory::getInstance().irisCam->rightHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, addPersonForm, &AddPersonForm::drawIrisImageOnFrame); + // 初始化电机控制 + ProMemory::getInstance().moto = new MotoController(this); + ProMemory::getInstance().moto->initSerialMCU(); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::motoControl, + ProMemory::getInstance().moto, &MotoController::autoPosition); + // 打印日志 LOG(INFO) << QString("应用程序启动成功[Application Startup Success]").toStdString(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::MAIN_PAGE; @@ -72,6 +79,10 @@ ProMemory::getInstance().irisRecogPro->deleteLater(); ProMemory::getInstance().irisRecogPro->wait(); + ProMemory::getInstance().camPosCtrl->exitThread(); + ProMemory::getInstance().camPosCtrl->deleteLater(); + ProMemory::getInstance().camPosCtrl->wait(); + // 关闭自动启动的外部程序 // outExe->close(); // delete outExe; @@ -81,12 +92,14 @@ delete ProMemory::getInstance().faceRecogPro; delete ProMemory::getInstance().irisRegistPro; delete ProMemory::getInstance().irisRecogPro; + delete ProMemory::getInstance().camPosCtrl; } void CasicBioRecWin::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: + LOG(INFO) << "" << std::endl; QTimer::singleShot(100, qApp, SLOT(quit())); default: @@ -204,8 +217,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -244,8 +255,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -255,3 +264,17 @@ ProMemory::getInstance().irisRecogPro->start(); } + +void CasicBioRecWin::initCameraPositionThread() +{ + // 调整相机位置处理 + ProMemory::getInstance().camPosCtrl = new CameraPositionController(this); + + // 绑定信号与槽函数 + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTips, + recogResultForm, &RecognizeResultForm::updateRecogTips); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTipsBackgroundColor, + recogResultForm, &RecognizeResultForm::updateRecogTipsColor); + + ProMemory::getInstance().camPosCtrl->start(); +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h index b70245a..b5a3db9 100644 --- a/CasicBioRecWin.h +++ b/CasicBioRecWin.h @@ -54,6 +54,7 @@ void initFaceRecogThread(); void initIrisRegistThread(); void initIrisRecogThread(); + void initCameraPositionThread(); }; #endif // CASICBIORECWIN_H diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp index f202cfe..bc8018b 100644 --- a/CasicBioRecWin.cpp +++ b/CasicBioRecWin.cpp @@ -6,7 +6,7 @@ , ui(new Ui::CasicBioRecWin) { // 打开外部可执行程序 - outExe = new QProcess(this); +// outExe = new QProcess(this); // outExe->start(SettingConfig::getInstance().OUT_EXE_FILE); ui->setupUi(this); @@ -31,6 +31,7 @@ initFaceRecogThread(); // 人脸识别线程 initIrisRegistThread(); // 虹膜注册线程 initIrisRecogThread(); // 虹膜识别线程 + initCameraPositionThread(); // 调整相机位置 // 初始化人脸相机控制 ProMemory::getInstance().faceCam = new FaceCameraController(this); @@ -49,6 +50,12 @@ connect(ProMemory::getInstance().irisCam->rightHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, addPersonForm, &AddPersonForm::drawIrisImageOnFrame); + // 初始化电机控制 + ProMemory::getInstance().moto = new MotoController(this); + ProMemory::getInstance().moto->initSerialMCU(); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::motoControl, + ProMemory::getInstance().moto, &MotoController::autoPosition); + // 打印日志 LOG(INFO) << QString("应用程序启动成功[Application Startup Success]").toStdString(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::MAIN_PAGE; @@ -72,6 +79,10 @@ ProMemory::getInstance().irisRecogPro->deleteLater(); ProMemory::getInstance().irisRecogPro->wait(); + ProMemory::getInstance().camPosCtrl->exitThread(); + ProMemory::getInstance().camPosCtrl->deleteLater(); + ProMemory::getInstance().camPosCtrl->wait(); + // 关闭自动启动的外部程序 // outExe->close(); // delete outExe; @@ -81,12 +92,14 @@ delete ProMemory::getInstance().faceRecogPro; delete ProMemory::getInstance().irisRegistPro; delete ProMemory::getInstance().irisRecogPro; + delete ProMemory::getInstance().camPosCtrl; } void CasicBioRecWin::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: + LOG(INFO) << "" << std::endl; QTimer::singleShot(100, qApp, SLOT(quit())); default: @@ -204,8 +217,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -244,8 +255,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -255,3 +264,17 @@ ProMemory::getInstance().irisRecogPro->start(); } + +void CasicBioRecWin::initCameraPositionThread() +{ + // 调整相机位置处理 + ProMemory::getInstance().camPosCtrl = new CameraPositionController(this); + + // 绑定信号与槽函数 + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTips, + recogResultForm, &RecognizeResultForm::updateRecogTips); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTipsBackgroundColor, + recogResultForm, &RecognizeResultForm::updateRecogTipsColor); + + ProMemory::getInstance().camPosCtrl->start(); +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h index b70245a..b5a3db9 100644 --- a/CasicBioRecWin.h +++ b/CasicBioRecWin.h @@ -54,6 +54,7 @@ void initFaceRecogThread(); void initIrisRegistThread(); void initIrisRecogThread(); + void initCameraPositionThread(); }; #endif // CASICBIORECWIN_H diff --git a/RecognizeResultForm.cpp b/RecognizeResultForm.cpp index e45a191..b340be9 100644 --- a/RecognizeResultForm.cpp +++ b/RecognizeResultForm.cpp @@ -20,7 +20,7 @@ RecognizeResultForm::~RecognizeResultForm() { - delete ui; + delete ui; } void RecognizeResultForm::startWorkingRecognize() @@ -29,23 +29,32 @@ switch (SettingConfig::getInstance().RECOG_TYPE) { case 1: // 人脸识别 + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); break; case 2: // 虹膜识别 + ProMemory::getInstance().clearIrisQueue(); +// ProMemory::getInstance().camPosCtrl->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; case 3: + // 双认证 先打开人脸识别 成功后再进行虹膜识别 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(true); + break; case 4: // 人脸和虹膜都需要打开 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; } - // 将界面切换到识别界面 RecognizeResultForm + // 开始拍图并显示视频 ProMemory::getInstance().faceCam->openFaceCamera(SettingConfig::getInstance().FACE_FRAME_INTERVAL); ui->labBackground->raise(); @@ -80,6 +89,14 @@ ui->widgetFail->raise(); ui->widgetFail->show(); + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().camPosCtrl->setWorking(false); + + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(false); + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ ui->labBackground->raise(); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -137,9 +154,9 @@ case 1: { // 仅人脸识别 - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); LOG(DEBUG) << QString("[RecognizeResultForm] 人脸识别成功 [%1]").arg(CasicFaceRecState::getInstance().toString()).toStdString(); @@ -158,9 +175,12 @@ case 2: { // 仅虹膜识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + // 停止控制电机和提示 + ProMemory::getInstance().camPosCtrl->setWorking(false); LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜识别成功 [%1]").arg(CasicIrisRecState::getInstance().toString()).toStdString(); @@ -179,13 +199,13 @@ case 4: { // 任意识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); QString logStr = QString("[RecognizeResultForm]%1识别成功[%2]"); if (faceOrIris == 1) @@ -213,42 +233,56 @@ if (faceOrIris == 1) { this->personIdByFace = personId; + + // 人脸识别成功后 开始进行虹膜识别 + // 1. 首先停止人脸识别 + ProMemory::getInstance().faceRecogPro->setWorking(false); + ProMemory::getInstance().clearFaceQueue(); + + // 2. 虹膜识别开始 + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().camPosCtrl->setWorking(true); } else if (faceOrIris == 2) { this->personIdByIris = personId; + + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) + { + // 只有一个成功的结果 需要等待下次 + return; + } else if (personIdByFace != personIdByIris) + { + // 人脸和虹膜识别的不是同一人 识别失败 + LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); + SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); + showRecogFailure(); + } else + { + LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); + showRecognizeResult(personId); + + // 识别记录存入数据库 + RecognitionRecordDao recDao; + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("type", "3"); + record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); + recDao.save(record); + } } - - if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) - { - // 只有一个成功的结果 需要等待下次 - return; - } else if (personIdByFace != personIdByIris) - { - // 人脸和虹膜识别的不是同一人 识别失败 - LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); - SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); - showRecogFailure(); - } else - { - LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); - showRecognizeResult(personId); - } - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - ProMemory::getInstance().clearFaceQueue(); - ProMemory::getInstance().faceRecogPro->setWorking(false); - ProMemory::getInstance().faceCam->stopTakingPhoto(); - - // 识别记录存入数据库 - RecognitionRecordDao recDao; - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("type", "4"); - record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); - recDao.save(record); } } + +void RecognizeResultForm::updateRecogTips(QString tipsText) +{ + ui->labTitle->setText(tipsText); +} +void RecognizeResultForm::updateRecogTipsColor(QString bgColor) +{ + ui->labTitle->setStyleSheet("background: " + bgColor); +} diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp index f202cfe..bc8018b 100644 --- a/CasicBioRecWin.cpp +++ b/CasicBioRecWin.cpp @@ -6,7 +6,7 @@ , ui(new Ui::CasicBioRecWin) { // 打开外部可执行程序 - outExe = new QProcess(this); +// outExe = new QProcess(this); // outExe->start(SettingConfig::getInstance().OUT_EXE_FILE); ui->setupUi(this); @@ -31,6 +31,7 @@ initFaceRecogThread(); // 人脸识别线程 initIrisRegistThread(); // 虹膜注册线程 initIrisRecogThread(); // 虹膜识别线程 + initCameraPositionThread(); // 调整相机位置 // 初始化人脸相机控制 ProMemory::getInstance().faceCam = new FaceCameraController(this); @@ -49,6 +50,12 @@ connect(ProMemory::getInstance().irisCam->rightHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, addPersonForm, &AddPersonForm::drawIrisImageOnFrame); + // 初始化电机控制 + ProMemory::getInstance().moto = new MotoController(this); + ProMemory::getInstance().moto->initSerialMCU(); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::motoControl, + ProMemory::getInstance().moto, &MotoController::autoPosition); + // 打印日志 LOG(INFO) << QString("应用程序启动成功[Application Startup Success]").toStdString(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::MAIN_PAGE; @@ -72,6 +79,10 @@ ProMemory::getInstance().irisRecogPro->deleteLater(); ProMemory::getInstance().irisRecogPro->wait(); + ProMemory::getInstance().camPosCtrl->exitThread(); + ProMemory::getInstance().camPosCtrl->deleteLater(); + ProMemory::getInstance().camPosCtrl->wait(); + // 关闭自动启动的外部程序 // outExe->close(); // delete outExe; @@ -81,12 +92,14 @@ delete ProMemory::getInstance().faceRecogPro; delete ProMemory::getInstance().irisRegistPro; delete ProMemory::getInstance().irisRecogPro; + delete ProMemory::getInstance().camPosCtrl; } void CasicBioRecWin::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: + LOG(INFO) << "" << std::endl; QTimer::singleShot(100, qApp, SLOT(quit())); default: @@ -204,8 +217,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -244,8 +255,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -255,3 +264,17 @@ ProMemory::getInstance().irisRecogPro->start(); } + +void CasicBioRecWin::initCameraPositionThread() +{ + // 调整相机位置处理 + ProMemory::getInstance().camPosCtrl = new CameraPositionController(this); + + // 绑定信号与槽函数 + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTips, + recogResultForm, &RecognizeResultForm::updateRecogTips); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTipsBackgroundColor, + recogResultForm, &RecognizeResultForm::updateRecogTipsColor); + + ProMemory::getInstance().camPosCtrl->start(); +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h index b70245a..b5a3db9 100644 --- a/CasicBioRecWin.h +++ b/CasicBioRecWin.h @@ -54,6 +54,7 @@ void initFaceRecogThread(); void initIrisRegistThread(); void initIrisRecogThread(); + void initCameraPositionThread(); }; #endif // CASICBIORECWIN_H diff --git a/RecognizeResultForm.cpp b/RecognizeResultForm.cpp index e45a191..b340be9 100644 --- a/RecognizeResultForm.cpp +++ b/RecognizeResultForm.cpp @@ -20,7 +20,7 @@ RecognizeResultForm::~RecognizeResultForm() { - delete ui; + delete ui; } void RecognizeResultForm::startWorkingRecognize() @@ -29,23 +29,32 @@ switch (SettingConfig::getInstance().RECOG_TYPE) { case 1: // 人脸识别 + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); break; case 2: // 虹膜识别 + ProMemory::getInstance().clearIrisQueue(); +// ProMemory::getInstance().camPosCtrl->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; case 3: + // 双认证 先打开人脸识别 成功后再进行虹膜识别 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(true); + break; case 4: // 人脸和虹膜都需要打开 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; } - // 将界面切换到识别界面 RecognizeResultForm + // 开始拍图并显示视频 ProMemory::getInstance().faceCam->openFaceCamera(SettingConfig::getInstance().FACE_FRAME_INTERVAL); ui->labBackground->raise(); @@ -80,6 +89,14 @@ ui->widgetFail->raise(); ui->widgetFail->show(); + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().camPosCtrl->setWorking(false); + + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(false); + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ ui->labBackground->raise(); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -137,9 +154,9 @@ case 1: { // 仅人脸识别 - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); LOG(DEBUG) << QString("[RecognizeResultForm] 人脸识别成功 [%1]").arg(CasicFaceRecState::getInstance().toString()).toStdString(); @@ -158,9 +175,12 @@ case 2: { // 仅虹膜识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + // 停止控制电机和提示 + ProMemory::getInstance().camPosCtrl->setWorking(false); LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜识别成功 [%1]").arg(CasicIrisRecState::getInstance().toString()).toStdString(); @@ -179,13 +199,13 @@ case 4: { // 任意识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); QString logStr = QString("[RecognizeResultForm]%1识别成功[%2]"); if (faceOrIris == 1) @@ -213,42 +233,56 @@ if (faceOrIris == 1) { this->personIdByFace = personId; + + // 人脸识别成功后 开始进行虹膜识别 + // 1. 首先停止人脸识别 + ProMemory::getInstance().faceRecogPro->setWorking(false); + ProMemory::getInstance().clearFaceQueue(); + + // 2. 虹膜识别开始 + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().camPosCtrl->setWorking(true); } else if (faceOrIris == 2) { this->personIdByIris = personId; + + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) + { + // 只有一个成功的结果 需要等待下次 + return; + } else if (personIdByFace != personIdByIris) + { + // 人脸和虹膜识别的不是同一人 识别失败 + LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); + SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); + showRecogFailure(); + } else + { + LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); + showRecognizeResult(personId); + + // 识别记录存入数据库 + RecognitionRecordDao recDao; + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("type", "3"); + record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); + recDao.save(record); + } } - - if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) - { - // 只有一个成功的结果 需要等待下次 - return; - } else if (personIdByFace != personIdByIris) - { - // 人脸和虹膜识别的不是同一人 识别失败 - LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); - SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); - showRecogFailure(); - } else - { - LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); - showRecognizeResult(personId); - } - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - ProMemory::getInstance().clearFaceQueue(); - ProMemory::getInstance().faceRecogPro->setWorking(false); - ProMemory::getInstance().faceCam->stopTakingPhoto(); - - // 识别记录存入数据库 - RecognitionRecordDao recDao; - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("type", "4"); - record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); - recDao.save(record); } } + +void RecognizeResultForm::updateRecogTips(QString tipsText) +{ + ui->labTitle->setText(tipsText); +} +void RecognizeResultForm::updateRecogTipsColor(QString bgColor) +{ + ui->labTitle->setStyleSheet("background: " + bgColor); +} diff --git a/RecognizeResultForm.h b/RecognizeResultForm.h index 2c51865..65dd8ad 100644 --- a/RecognizeResultForm.h +++ b/RecognizeResultForm.h @@ -30,6 +30,8 @@ void startWorkingRecognize(); // 开始工作 void drawImageOnHomeForm(QImage imageDisp); + void updateRecogTips(QString tipsText); + void updateRecogTipsColor(QString bgColor); private: Ui::RecognizeResultForm *ui; diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp index f202cfe..bc8018b 100644 --- a/CasicBioRecWin.cpp +++ b/CasicBioRecWin.cpp @@ -6,7 +6,7 @@ , ui(new Ui::CasicBioRecWin) { // 打开外部可执行程序 - outExe = new QProcess(this); +// outExe = new QProcess(this); // outExe->start(SettingConfig::getInstance().OUT_EXE_FILE); ui->setupUi(this); @@ -31,6 +31,7 @@ initFaceRecogThread(); // 人脸识别线程 initIrisRegistThread(); // 虹膜注册线程 initIrisRecogThread(); // 虹膜识别线程 + initCameraPositionThread(); // 调整相机位置 // 初始化人脸相机控制 ProMemory::getInstance().faceCam = new FaceCameraController(this); @@ -49,6 +50,12 @@ connect(ProMemory::getInstance().irisCam->rightHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, addPersonForm, &AddPersonForm::drawIrisImageOnFrame); + // 初始化电机控制 + ProMemory::getInstance().moto = new MotoController(this); + ProMemory::getInstance().moto->initSerialMCU(); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::motoControl, + ProMemory::getInstance().moto, &MotoController::autoPosition); + // 打印日志 LOG(INFO) << QString("应用程序启动成功[Application Startup Success]").toStdString(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::MAIN_PAGE; @@ -72,6 +79,10 @@ ProMemory::getInstance().irisRecogPro->deleteLater(); ProMemory::getInstance().irisRecogPro->wait(); + ProMemory::getInstance().camPosCtrl->exitThread(); + ProMemory::getInstance().camPosCtrl->deleteLater(); + ProMemory::getInstance().camPosCtrl->wait(); + // 关闭自动启动的外部程序 // outExe->close(); // delete outExe; @@ -81,12 +92,14 @@ delete ProMemory::getInstance().faceRecogPro; delete ProMemory::getInstance().irisRegistPro; delete ProMemory::getInstance().irisRecogPro; + delete ProMemory::getInstance().camPosCtrl; } void CasicBioRecWin::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: + LOG(INFO) << "" << std::endl; QTimer::singleShot(100, qApp, SLOT(quit())); default: @@ -204,8 +217,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -244,8 +255,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -255,3 +264,17 @@ ProMemory::getInstance().irisRecogPro->start(); } + +void CasicBioRecWin::initCameraPositionThread() +{ + // 调整相机位置处理 + ProMemory::getInstance().camPosCtrl = new CameraPositionController(this); + + // 绑定信号与槽函数 + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTips, + recogResultForm, &RecognizeResultForm::updateRecogTips); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTipsBackgroundColor, + recogResultForm, &RecognizeResultForm::updateRecogTipsColor); + + ProMemory::getInstance().camPosCtrl->start(); +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h index b70245a..b5a3db9 100644 --- a/CasicBioRecWin.h +++ b/CasicBioRecWin.h @@ -54,6 +54,7 @@ void initFaceRecogThread(); void initIrisRegistThread(); void initIrisRecogThread(); + void initCameraPositionThread(); }; #endif // CASICBIORECWIN_H diff --git a/RecognizeResultForm.cpp b/RecognizeResultForm.cpp index e45a191..b340be9 100644 --- a/RecognizeResultForm.cpp +++ b/RecognizeResultForm.cpp @@ -20,7 +20,7 @@ RecognizeResultForm::~RecognizeResultForm() { - delete ui; + delete ui; } void RecognizeResultForm::startWorkingRecognize() @@ -29,23 +29,32 @@ switch (SettingConfig::getInstance().RECOG_TYPE) { case 1: // 人脸识别 + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); break; case 2: // 虹膜识别 + ProMemory::getInstance().clearIrisQueue(); +// ProMemory::getInstance().camPosCtrl->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; case 3: + // 双认证 先打开人脸识别 成功后再进行虹膜识别 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(true); + break; case 4: // 人脸和虹膜都需要打开 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; } - // 将界面切换到识别界面 RecognizeResultForm + // 开始拍图并显示视频 ProMemory::getInstance().faceCam->openFaceCamera(SettingConfig::getInstance().FACE_FRAME_INTERVAL); ui->labBackground->raise(); @@ -80,6 +89,14 @@ ui->widgetFail->raise(); ui->widgetFail->show(); + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().camPosCtrl->setWorking(false); + + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(false); + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ ui->labBackground->raise(); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -137,9 +154,9 @@ case 1: { // 仅人脸识别 - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); LOG(DEBUG) << QString("[RecognizeResultForm] 人脸识别成功 [%1]").arg(CasicFaceRecState::getInstance().toString()).toStdString(); @@ -158,9 +175,12 @@ case 2: { // 仅虹膜识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + // 停止控制电机和提示 + ProMemory::getInstance().camPosCtrl->setWorking(false); LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜识别成功 [%1]").arg(CasicIrisRecState::getInstance().toString()).toStdString(); @@ -179,13 +199,13 @@ case 4: { // 任意识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); QString logStr = QString("[RecognizeResultForm]%1识别成功[%2]"); if (faceOrIris == 1) @@ -213,42 +233,56 @@ if (faceOrIris == 1) { this->personIdByFace = personId; + + // 人脸识别成功后 开始进行虹膜识别 + // 1. 首先停止人脸识别 + ProMemory::getInstance().faceRecogPro->setWorking(false); + ProMemory::getInstance().clearFaceQueue(); + + // 2. 虹膜识别开始 + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().camPosCtrl->setWorking(true); } else if (faceOrIris == 2) { this->personIdByIris = personId; + + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) + { + // 只有一个成功的结果 需要等待下次 + return; + } else if (personIdByFace != personIdByIris) + { + // 人脸和虹膜识别的不是同一人 识别失败 + LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); + SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); + showRecogFailure(); + } else + { + LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); + showRecognizeResult(personId); + + // 识别记录存入数据库 + RecognitionRecordDao recDao; + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("type", "3"); + record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); + recDao.save(record); + } } - - if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) - { - // 只有一个成功的结果 需要等待下次 - return; - } else if (personIdByFace != personIdByIris) - { - // 人脸和虹膜识别的不是同一人 识别失败 - LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); - SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); - showRecogFailure(); - } else - { - LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); - showRecognizeResult(personId); - } - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - ProMemory::getInstance().clearFaceQueue(); - ProMemory::getInstance().faceRecogPro->setWorking(false); - ProMemory::getInstance().faceCam->stopTakingPhoto(); - - // 识别记录存入数据库 - RecognitionRecordDao recDao; - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("type", "4"); - record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); - recDao.save(record); } } + +void RecognizeResultForm::updateRecogTips(QString tipsText) +{ + ui->labTitle->setText(tipsText); +} +void RecognizeResultForm::updateRecogTipsColor(QString bgColor) +{ + ui->labTitle->setStyleSheet("background: " + bgColor); +} diff --git a/RecognizeResultForm.h b/RecognizeResultForm.h index 2c51865..65dd8ad 100644 --- a/RecognizeResultForm.h +++ b/RecognizeResultForm.h @@ -30,6 +30,8 @@ void startWorkingRecognize(); // 开始工作 void drawImageOnHomeForm(QImage imageDisp); + void updateRecogTips(QString tipsText); + void updateRecogTipsColor(QString bgColor); private: Ui::RecognizeResultForm *ui; diff --git a/StartupForm.cpp b/StartupForm.cpp index 16c4dfc..cf20de1 100644 --- a/StartupForm.cpp +++ b/StartupForm.cpp @@ -20,17 +20,23 @@ } // 设置弹簧的高度和宽度 - ui->vsTop->changeSize(0, 200); - ui->vsMidd->changeSize(0, 100); ui->hsLeft->changeSize(400, 0); ui->hsMidd->changeSize(150, 0); + // 绑定时间和日期的标签单击事件 单击即开始识别 + connect(ui->labDate, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + connect(ui->labTime, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + // 初始化更新界面的定时器 // 每秒执行一次 connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &StartupForm::updateDateAndTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, - this, &StartupForm::takeOneFrameForCheckStatus); +// connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, +// this, &StartupForm::takeOneFrameForCheckStatus); TimeCounterUtil::getInstance().clockCounter->start(1000); } diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp index f202cfe..bc8018b 100644 --- a/CasicBioRecWin.cpp +++ b/CasicBioRecWin.cpp @@ -6,7 +6,7 @@ , ui(new Ui::CasicBioRecWin) { // 打开外部可执行程序 - outExe = new QProcess(this); +// outExe = new QProcess(this); // outExe->start(SettingConfig::getInstance().OUT_EXE_FILE); ui->setupUi(this); @@ -31,6 +31,7 @@ initFaceRecogThread(); // 人脸识别线程 initIrisRegistThread(); // 虹膜注册线程 initIrisRecogThread(); // 虹膜识别线程 + initCameraPositionThread(); // 调整相机位置 // 初始化人脸相机控制 ProMemory::getInstance().faceCam = new FaceCameraController(this); @@ -49,6 +50,12 @@ connect(ProMemory::getInstance().irisCam->rightHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, addPersonForm, &AddPersonForm::drawIrisImageOnFrame); + // 初始化电机控制 + ProMemory::getInstance().moto = new MotoController(this); + ProMemory::getInstance().moto->initSerialMCU(); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::motoControl, + ProMemory::getInstance().moto, &MotoController::autoPosition); + // 打印日志 LOG(INFO) << QString("应用程序启动成功[Application Startup Success]").toStdString(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::MAIN_PAGE; @@ -72,6 +79,10 @@ ProMemory::getInstance().irisRecogPro->deleteLater(); ProMemory::getInstance().irisRecogPro->wait(); + ProMemory::getInstance().camPosCtrl->exitThread(); + ProMemory::getInstance().camPosCtrl->deleteLater(); + ProMemory::getInstance().camPosCtrl->wait(); + // 关闭自动启动的外部程序 // outExe->close(); // delete outExe; @@ -81,12 +92,14 @@ delete ProMemory::getInstance().faceRecogPro; delete ProMemory::getInstance().irisRegistPro; delete ProMemory::getInstance().irisRecogPro; + delete ProMemory::getInstance().camPosCtrl; } void CasicBioRecWin::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: + LOG(INFO) << "" << std::endl; QTimer::singleShot(100, qApp, SLOT(quit())); default: @@ -204,8 +217,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -244,8 +255,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -255,3 +264,17 @@ ProMemory::getInstance().irisRecogPro->start(); } + +void CasicBioRecWin::initCameraPositionThread() +{ + // 调整相机位置处理 + ProMemory::getInstance().camPosCtrl = new CameraPositionController(this); + + // 绑定信号与槽函数 + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTips, + recogResultForm, &RecognizeResultForm::updateRecogTips); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTipsBackgroundColor, + recogResultForm, &RecognizeResultForm::updateRecogTipsColor); + + ProMemory::getInstance().camPosCtrl->start(); +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h index b70245a..b5a3db9 100644 --- a/CasicBioRecWin.h +++ b/CasicBioRecWin.h @@ -54,6 +54,7 @@ void initFaceRecogThread(); void initIrisRegistThread(); void initIrisRecogThread(); + void initCameraPositionThread(); }; #endif // CASICBIORECWIN_H diff --git a/RecognizeResultForm.cpp b/RecognizeResultForm.cpp index e45a191..b340be9 100644 --- a/RecognizeResultForm.cpp +++ b/RecognizeResultForm.cpp @@ -20,7 +20,7 @@ RecognizeResultForm::~RecognizeResultForm() { - delete ui; + delete ui; } void RecognizeResultForm::startWorkingRecognize() @@ -29,23 +29,32 @@ switch (SettingConfig::getInstance().RECOG_TYPE) { case 1: // 人脸识别 + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); break; case 2: // 虹膜识别 + ProMemory::getInstance().clearIrisQueue(); +// ProMemory::getInstance().camPosCtrl->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; case 3: + // 双认证 先打开人脸识别 成功后再进行虹膜识别 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(true); + break; case 4: // 人脸和虹膜都需要打开 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; } - // 将界面切换到识别界面 RecognizeResultForm + // 开始拍图并显示视频 ProMemory::getInstance().faceCam->openFaceCamera(SettingConfig::getInstance().FACE_FRAME_INTERVAL); ui->labBackground->raise(); @@ -80,6 +89,14 @@ ui->widgetFail->raise(); ui->widgetFail->show(); + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().camPosCtrl->setWorking(false); + + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(false); + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ ui->labBackground->raise(); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -137,9 +154,9 @@ case 1: { // 仅人脸识别 - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); LOG(DEBUG) << QString("[RecognizeResultForm] 人脸识别成功 [%1]").arg(CasicFaceRecState::getInstance().toString()).toStdString(); @@ -158,9 +175,12 @@ case 2: { // 仅虹膜识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + // 停止控制电机和提示 + ProMemory::getInstance().camPosCtrl->setWorking(false); LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜识别成功 [%1]").arg(CasicIrisRecState::getInstance().toString()).toStdString(); @@ -179,13 +199,13 @@ case 4: { // 任意识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); QString logStr = QString("[RecognizeResultForm]%1识别成功[%2]"); if (faceOrIris == 1) @@ -213,42 +233,56 @@ if (faceOrIris == 1) { this->personIdByFace = personId; + + // 人脸识别成功后 开始进行虹膜识别 + // 1. 首先停止人脸识别 + ProMemory::getInstance().faceRecogPro->setWorking(false); + ProMemory::getInstance().clearFaceQueue(); + + // 2. 虹膜识别开始 + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().camPosCtrl->setWorking(true); } else if (faceOrIris == 2) { this->personIdByIris = personId; + + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) + { + // 只有一个成功的结果 需要等待下次 + return; + } else if (personIdByFace != personIdByIris) + { + // 人脸和虹膜识别的不是同一人 识别失败 + LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); + SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); + showRecogFailure(); + } else + { + LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); + showRecognizeResult(personId); + + // 识别记录存入数据库 + RecognitionRecordDao recDao; + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("type", "3"); + record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); + recDao.save(record); + } } - - if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) - { - // 只有一个成功的结果 需要等待下次 - return; - } else if (personIdByFace != personIdByIris) - { - // 人脸和虹膜识别的不是同一人 识别失败 - LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); - SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); - showRecogFailure(); - } else - { - LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); - showRecognizeResult(personId); - } - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - ProMemory::getInstance().clearFaceQueue(); - ProMemory::getInstance().faceRecogPro->setWorking(false); - ProMemory::getInstance().faceCam->stopTakingPhoto(); - - // 识别记录存入数据库 - RecognitionRecordDao recDao; - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("type", "4"); - record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); - recDao.save(record); } } + +void RecognizeResultForm::updateRecogTips(QString tipsText) +{ + ui->labTitle->setText(tipsText); +} +void RecognizeResultForm::updateRecogTipsColor(QString bgColor) +{ + ui->labTitle->setStyleSheet("background: " + bgColor); +} diff --git a/RecognizeResultForm.h b/RecognizeResultForm.h index 2c51865..65dd8ad 100644 --- a/RecognizeResultForm.h +++ b/RecognizeResultForm.h @@ -30,6 +30,8 @@ void startWorkingRecognize(); // 开始工作 void drawImageOnHomeForm(QImage imageDisp); + void updateRecogTips(QString tipsText); + void updateRecogTipsColor(QString bgColor); private: Ui::RecognizeResultForm *ui; diff --git a/StartupForm.cpp b/StartupForm.cpp index 16c4dfc..cf20de1 100644 --- a/StartupForm.cpp +++ b/StartupForm.cpp @@ -20,17 +20,23 @@ } // 设置弹簧的高度和宽度 - ui->vsTop->changeSize(0, 200); - ui->vsMidd->changeSize(0, 100); ui->hsLeft->changeSize(400, 0); ui->hsMidd->changeSize(150, 0); + // 绑定时间和日期的标签单击事件 单击即开始识别 + connect(ui->labDate, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + connect(ui->labTime, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + // 初始化更新界面的定时器 // 每秒执行一次 connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &StartupForm::updateDateAndTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, - this, &StartupForm::takeOneFrameForCheckStatus); +// connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, +// this, &StartupForm::takeOneFrameForCheckStatus); TimeCounterUtil::getInstance().clockCounter->start(1000); } diff --git a/StartupForm.h b/StartupForm.h index f2850e9..fc79be0 100644 --- a/StartupForm.h +++ b/StartupForm.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "casic/ProMemory.h" #include "utils/UtilInclude.h" diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp index f202cfe..bc8018b 100644 --- a/CasicBioRecWin.cpp +++ b/CasicBioRecWin.cpp @@ -6,7 +6,7 @@ , ui(new Ui::CasicBioRecWin) { // 打开外部可执行程序 - outExe = new QProcess(this); +// outExe = new QProcess(this); // outExe->start(SettingConfig::getInstance().OUT_EXE_FILE); ui->setupUi(this); @@ -31,6 +31,7 @@ initFaceRecogThread(); // 人脸识别线程 initIrisRegistThread(); // 虹膜注册线程 initIrisRecogThread(); // 虹膜识别线程 + initCameraPositionThread(); // 调整相机位置 // 初始化人脸相机控制 ProMemory::getInstance().faceCam = new FaceCameraController(this); @@ -49,6 +50,12 @@ connect(ProMemory::getInstance().irisCam->rightHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, addPersonForm, &AddPersonForm::drawIrisImageOnFrame); + // 初始化电机控制 + ProMemory::getInstance().moto = new MotoController(this); + ProMemory::getInstance().moto->initSerialMCU(); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::motoControl, + ProMemory::getInstance().moto, &MotoController::autoPosition); + // 打印日志 LOG(INFO) << QString("应用程序启动成功[Application Startup Success]").toStdString(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::MAIN_PAGE; @@ -72,6 +79,10 @@ ProMemory::getInstance().irisRecogPro->deleteLater(); ProMemory::getInstance().irisRecogPro->wait(); + ProMemory::getInstance().camPosCtrl->exitThread(); + ProMemory::getInstance().camPosCtrl->deleteLater(); + ProMemory::getInstance().camPosCtrl->wait(); + // 关闭自动启动的外部程序 // outExe->close(); // delete outExe; @@ -81,12 +92,14 @@ delete ProMemory::getInstance().faceRecogPro; delete ProMemory::getInstance().irisRegistPro; delete ProMemory::getInstance().irisRecogPro; + delete ProMemory::getInstance().camPosCtrl; } void CasicBioRecWin::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: + LOG(INFO) << "" << std::endl; QTimer::singleShot(100, qApp, SLOT(quit())); default: @@ -204,8 +217,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -244,8 +255,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -255,3 +264,17 @@ ProMemory::getInstance().irisRecogPro->start(); } + +void CasicBioRecWin::initCameraPositionThread() +{ + // 调整相机位置处理 + ProMemory::getInstance().camPosCtrl = new CameraPositionController(this); + + // 绑定信号与槽函数 + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTips, + recogResultForm, &RecognizeResultForm::updateRecogTips); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTipsBackgroundColor, + recogResultForm, &RecognizeResultForm::updateRecogTipsColor); + + ProMemory::getInstance().camPosCtrl->start(); +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h index b70245a..b5a3db9 100644 --- a/CasicBioRecWin.h +++ b/CasicBioRecWin.h @@ -54,6 +54,7 @@ void initFaceRecogThread(); void initIrisRegistThread(); void initIrisRecogThread(); + void initCameraPositionThread(); }; #endif // CASICBIORECWIN_H diff --git a/RecognizeResultForm.cpp b/RecognizeResultForm.cpp index e45a191..b340be9 100644 --- a/RecognizeResultForm.cpp +++ b/RecognizeResultForm.cpp @@ -20,7 +20,7 @@ RecognizeResultForm::~RecognizeResultForm() { - delete ui; + delete ui; } void RecognizeResultForm::startWorkingRecognize() @@ -29,23 +29,32 @@ switch (SettingConfig::getInstance().RECOG_TYPE) { case 1: // 人脸识别 + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); break; case 2: // 虹膜识别 + ProMemory::getInstance().clearIrisQueue(); +// ProMemory::getInstance().camPosCtrl->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; case 3: + // 双认证 先打开人脸识别 成功后再进行虹膜识别 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(true); + break; case 4: // 人脸和虹膜都需要打开 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; } - // 将界面切换到识别界面 RecognizeResultForm + // 开始拍图并显示视频 ProMemory::getInstance().faceCam->openFaceCamera(SettingConfig::getInstance().FACE_FRAME_INTERVAL); ui->labBackground->raise(); @@ -80,6 +89,14 @@ ui->widgetFail->raise(); ui->widgetFail->show(); + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().camPosCtrl->setWorking(false); + + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(false); + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ ui->labBackground->raise(); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -137,9 +154,9 @@ case 1: { // 仅人脸识别 - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); LOG(DEBUG) << QString("[RecognizeResultForm] 人脸识别成功 [%1]").arg(CasicFaceRecState::getInstance().toString()).toStdString(); @@ -158,9 +175,12 @@ case 2: { // 仅虹膜识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + // 停止控制电机和提示 + ProMemory::getInstance().camPosCtrl->setWorking(false); LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜识别成功 [%1]").arg(CasicIrisRecState::getInstance().toString()).toStdString(); @@ -179,13 +199,13 @@ case 4: { // 任意识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); QString logStr = QString("[RecognizeResultForm]%1识别成功[%2]"); if (faceOrIris == 1) @@ -213,42 +233,56 @@ if (faceOrIris == 1) { this->personIdByFace = personId; + + // 人脸识别成功后 开始进行虹膜识别 + // 1. 首先停止人脸识别 + ProMemory::getInstance().faceRecogPro->setWorking(false); + ProMemory::getInstance().clearFaceQueue(); + + // 2. 虹膜识别开始 + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().camPosCtrl->setWorking(true); } else if (faceOrIris == 2) { this->personIdByIris = personId; + + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) + { + // 只有一个成功的结果 需要等待下次 + return; + } else if (personIdByFace != personIdByIris) + { + // 人脸和虹膜识别的不是同一人 识别失败 + LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); + SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); + showRecogFailure(); + } else + { + LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); + showRecognizeResult(personId); + + // 识别记录存入数据库 + RecognitionRecordDao recDao; + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("type", "3"); + record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); + recDao.save(record); + } } - - if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) - { - // 只有一个成功的结果 需要等待下次 - return; - } else if (personIdByFace != personIdByIris) - { - // 人脸和虹膜识别的不是同一人 识别失败 - LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); - SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); - showRecogFailure(); - } else - { - LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); - showRecognizeResult(personId); - } - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - ProMemory::getInstance().clearFaceQueue(); - ProMemory::getInstance().faceRecogPro->setWorking(false); - ProMemory::getInstance().faceCam->stopTakingPhoto(); - - // 识别记录存入数据库 - RecognitionRecordDao recDao; - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("type", "4"); - record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); - recDao.save(record); } } + +void RecognizeResultForm::updateRecogTips(QString tipsText) +{ + ui->labTitle->setText(tipsText); +} +void RecognizeResultForm::updateRecogTipsColor(QString bgColor) +{ + ui->labTitle->setStyleSheet("background: " + bgColor); +} diff --git a/RecognizeResultForm.h b/RecognizeResultForm.h index 2c51865..65dd8ad 100644 --- a/RecognizeResultForm.h +++ b/RecognizeResultForm.h @@ -30,6 +30,8 @@ void startWorkingRecognize(); // 开始工作 void drawImageOnHomeForm(QImage imageDisp); + void updateRecogTips(QString tipsText); + void updateRecogTipsColor(QString bgColor); private: Ui::RecognizeResultForm *ui; diff --git a/StartupForm.cpp b/StartupForm.cpp index 16c4dfc..cf20de1 100644 --- a/StartupForm.cpp +++ b/StartupForm.cpp @@ -20,17 +20,23 @@ } // 设置弹簧的高度和宽度 - ui->vsTop->changeSize(0, 200); - ui->vsMidd->changeSize(0, 100); ui->hsLeft->changeSize(400, 0); ui->hsMidd->changeSize(150, 0); + // 绑定时间和日期的标签单击事件 单击即开始识别 + connect(ui->labDate, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + connect(ui->labTime, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + // 初始化更新界面的定时器 // 每秒执行一次 connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &StartupForm::updateDateAndTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, - this, &StartupForm::takeOneFrameForCheckStatus); +// connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, +// this, &StartupForm::takeOneFrameForCheckStatus); TimeCounterUtil::getInstance().clockCounter->start(1000); } diff --git a/StartupForm.h b/StartupForm.h index f2850e9..fc79be0 100644 --- a/StartupForm.h +++ b/StartupForm.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "casic/ProMemory.h" #include "utils/UtilInclude.h" diff --git a/StartupForm.ui b/StartupForm.ui index afb610f..de353f3 100644 --- a/StartupForm.ui +++ b/StartupForm.ui @@ -15,20 +15,7 @@ - - - Qt::Vertical - - - - 17 - 166 - - - - - - + TextLabel @@ -38,7 +25,7 @@ - + TextLabel @@ -48,19 +35,6 @@ - - - Qt::Vertical - - - - 17 - 167 - - - - - @@ -158,6 +132,13 @@ + + + QDblClickLabel + QLabel +
QDblClickLabel.h
+
+
diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp index f202cfe..bc8018b 100644 --- a/CasicBioRecWin.cpp +++ b/CasicBioRecWin.cpp @@ -6,7 +6,7 @@ , ui(new Ui::CasicBioRecWin) { // 打开外部可执行程序 - outExe = new QProcess(this); +// outExe = new QProcess(this); // outExe->start(SettingConfig::getInstance().OUT_EXE_FILE); ui->setupUi(this); @@ -31,6 +31,7 @@ initFaceRecogThread(); // 人脸识别线程 initIrisRegistThread(); // 虹膜注册线程 initIrisRecogThread(); // 虹膜识别线程 + initCameraPositionThread(); // 调整相机位置 // 初始化人脸相机控制 ProMemory::getInstance().faceCam = new FaceCameraController(this); @@ -49,6 +50,12 @@ connect(ProMemory::getInstance().irisCam->rightHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, addPersonForm, &AddPersonForm::drawIrisImageOnFrame); + // 初始化电机控制 + ProMemory::getInstance().moto = new MotoController(this); + ProMemory::getInstance().moto->initSerialMCU(); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::motoControl, + ProMemory::getInstance().moto, &MotoController::autoPosition); + // 打印日志 LOG(INFO) << QString("应用程序启动成功[Application Startup Success]").toStdString(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::MAIN_PAGE; @@ -72,6 +79,10 @@ ProMemory::getInstance().irisRecogPro->deleteLater(); ProMemory::getInstance().irisRecogPro->wait(); + ProMemory::getInstance().camPosCtrl->exitThread(); + ProMemory::getInstance().camPosCtrl->deleteLater(); + ProMemory::getInstance().camPosCtrl->wait(); + // 关闭自动启动的外部程序 // outExe->close(); // delete outExe; @@ -81,12 +92,14 @@ delete ProMemory::getInstance().faceRecogPro; delete ProMemory::getInstance().irisRegistPro; delete ProMemory::getInstance().irisRecogPro; + delete ProMemory::getInstance().camPosCtrl; } void CasicBioRecWin::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: + LOG(INFO) << "" << std::endl; QTimer::singleShot(100, qApp, SLOT(quit())); default: @@ -204,8 +217,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -244,8 +255,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -255,3 +264,17 @@ ProMemory::getInstance().irisRecogPro->start(); } + +void CasicBioRecWin::initCameraPositionThread() +{ + // 调整相机位置处理 + ProMemory::getInstance().camPosCtrl = new CameraPositionController(this); + + // 绑定信号与槽函数 + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTips, + recogResultForm, &RecognizeResultForm::updateRecogTips); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTipsBackgroundColor, + recogResultForm, &RecognizeResultForm::updateRecogTipsColor); + + ProMemory::getInstance().camPosCtrl->start(); +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h index b70245a..b5a3db9 100644 --- a/CasicBioRecWin.h +++ b/CasicBioRecWin.h @@ -54,6 +54,7 @@ void initFaceRecogThread(); void initIrisRegistThread(); void initIrisRecogThread(); + void initCameraPositionThread(); }; #endif // CASICBIORECWIN_H diff --git a/RecognizeResultForm.cpp b/RecognizeResultForm.cpp index e45a191..b340be9 100644 --- a/RecognizeResultForm.cpp +++ b/RecognizeResultForm.cpp @@ -20,7 +20,7 @@ RecognizeResultForm::~RecognizeResultForm() { - delete ui; + delete ui; } void RecognizeResultForm::startWorkingRecognize() @@ -29,23 +29,32 @@ switch (SettingConfig::getInstance().RECOG_TYPE) { case 1: // 人脸识别 + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); break; case 2: // 虹膜识别 + ProMemory::getInstance().clearIrisQueue(); +// ProMemory::getInstance().camPosCtrl->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; case 3: + // 双认证 先打开人脸识别 成功后再进行虹膜识别 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(true); + break; case 4: // 人脸和虹膜都需要打开 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; } - // 将界面切换到识别界面 RecognizeResultForm + // 开始拍图并显示视频 ProMemory::getInstance().faceCam->openFaceCamera(SettingConfig::getInstance().FACE_FRAME_INTERVAL); ui->labBackground->raise(); @@ -80,6 +89,14 @@ ui->widgetFail->raise(); ui->widgetFail->show(); + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().camPosCtrl->setWorking(false); + + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(false); + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ ui->labBackground->raise(); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -137,9 +154,9 @@ case 1: { // 仅人脸识别 - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); LOG(DEBUG) << QString("[RecognizeResultForm] 人脸识别成功 [%1]").arg(CasicFaceRecState::getInstance().toString()).toStdString(); @@ -158,9 +175,12 @@ case 2: { // 仅虹膜识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + // 停止控制电机和提示 + ProMemory::getInstance().camPosCtrl->setWorking(false); LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜识别成功 [%1]").arg(CasicIrisRecState::getInstance().toString()).toStdString(); @@ -179,13 +199,13 @@ case 4: { // 任意识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); QString logStr = QString("[RecognizeResultForm]%1识别成功[%2]"); if (faceOrIris == 1) @@ -213,42 +233,56 @@ if (faceOrIris == 1) { this->personIdByFace = personId; + + // 人脸识别成功后 开始进行虹膜识别 + // 1. 首先停止人脸识别 + ProMemory::getInstance().faceRecogPro->setWorking(false); + ProMemory::getInstance().clearFaceQueue(); + + // 2. 虹膜识别开始 + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().camPosCtrl->setWorking(true); } else if (faceOrIris == 2) { this->personIdByIris = personId; + + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) + { + // 只有一个成功的结果 需要等待下次 + return; + } else if (personIdByFace != personIdByIris) + { + // 人脸和虹膜识别的不是同一人 识别失败 + LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); + SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); + showRecogFailure(); + } else + { + LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); + showRecognizeResult(personId); + + // 识别记录存入数据库 + RecognitionRecordDao recDao; + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("type", "3"); + record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); + recDao.save(record); + } } - - if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) - { - // 只有一个成功的结果 需要等待下次 - return; - } else if (personIdByFace != personIdByIris) - { - // 人脸和虹膜识别的不是同一人 识别失败 - LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); - SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); - showRecogFailure(); - } else - { - LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); - showRecognizeResult(personId); - } - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - ProMemory::getInstance().clearFaceQueue(); - ProMemory::getInstance().faceRecogPro->setWorking(false); - ProMemory::getInstance().faceCam->stopTakingPhoto(); - - // 识别记录存入数据库 - RecognitionRecordDao recDao; - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("type", "4"); - record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); - recDao.save(record); } } + +void RecognizeResultForm::updateRecogTips(QString tipsText) +{ + ui->labTitle->setText(tipsText); +} +void RecognizeResultForm::updateRecogTipsColor(QString bgColor) +{ + ui->labTitle->setStyleSheet("background: " + bgColor); +} diff --git a/RecognizeResultForm.h b/RecognizeResultForm.h index 2c51865..65dd8ad 100644 --- a/RecognizeResultForm.h +++ b/RecognizeResultForm.h @@ -30,6 +30,8 @@ void startWorkingRecognize(); // 开始工作 void drawImageOnHomeForm(QImage imageDisp); + void updateRecogTips(QString tipsText); + void updateRecogTipsColor(QString bgColor); private: Ui::RecognizeResultForm *ui; diff --git a/StartupForm.cpp b/StartupForm.cpp index 16c4dfc..cf20de1 100644 --- a/StartupForm.cpp +++ b/StartupForm.cpp @@ -20,17 +20,23 @@ } // 设置弹簧的高度和宽度 - ui->vsTop->changeSize(0, 200); - ui->vsMidd->changeSize(0, 100); ui->hsLeft->changeSize(400, 0); ui->hsMidd->changeSize(150, 0); + // 绑定时间和日期的标签单击事件 单击即开始识别 + connect(ui->labDate, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + connect(ui->labTime, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + // 初始化更新界面的定时器 // 每秒执行一次 connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &StartupForm::updateDateAndTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, - this, &StartupForm::takeOneFrameForCheckStatus); +// connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, +// this, &StartupForm::takeOneFrameForCheckStatus); TimeCounterUtil::getInstance().clockCounter->start(1000); } diff --git a/StartupForm.h b/StartupForm.h index f2850e9..fc79be0 100644 --- a/StartupForm.h +++ b/StartupForm.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "casic/ProMemory.h" #include "utils/UtilInclude.h" diff --git a/StartupForm.ui b/StartupForm.ui index afb610f..de353f3 100644 --- a/StartupForm.ui +++ b/StartupForm.ui @@ -15,20 +15,7 @@ - - - Qt::Vertical - - - - 17 - 166 - - - - - - + TextLabel @@ -38,7 +25,7 @@ - + TextLabel @@ -48,19 +35,6 @@ - - - Qt::Vertical - - - - 17 - 167 - - - - - @@ -158,6 +132,13 @@ + + + QDblClickLabel + QLabel +
QDblClickLabel.h
+
+
diff --git a/casic/ProMemory.h b/casic/ProMemory.h index 3e9fbd4..02a14cf 100644 --- a/casic/ProMemory.h +++ b/casic/ProMemory.h @@ -16,6 +16,8 @@ #include "device/face/FaceRecogProcess.h" #include "device/iris/IrisRegistProcess.h" #include "device/iris/IrisRecogProcess.h" +#include "device/MotoController.h" +#include "device/CameraPositionController.h" class FaceCameraController; class IrisCameraController; @@ -23,6 +25,8 @@ class FaceRecogProcess; class IrisRegistProcess; class IrisRecogProcess; +class MotoController; +class CameraPositionController; class ProMemory { @@ -66,6 +70,10 @@ IrisRegistProcess * irisRegistPro; IrisRecogProcess * irisRecogPro; + MotoController * moto; + + CameraPositionController * camPosCtrl; + private: ProMemory(); diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp index f202cfe..bc8018b 100644 --- a/CasicBioRecWin.cpp +++ b/CasicBioRecWin.cpp @@ -6,7 +6,7 @@ , ui(new Ui::CasicBioRecWin) { // 打开外部可执行程序 - outExe = new QProcess(this); +// outExe = new QProcess(this); // outExe->start(SettingConfig::getInstance().OUT_EXE_FILE); ui->setupUi(this); @@ -31,6 +31,7 @@ initFaceRecogThread(); // 人脸识别线程 initIrisRegistThread(); // 虹膜注册线程 initIrisRecogThread(); // 虹膜识别线程 + initCameraPositionThread(); // 调整相机位置 // 初始化人脸相机控制 ProMemory::getInstance().faceCam = new FaceCameraController(this); @@ -49,6 +50,12 @@ connect(ProMemory::getInstance().irisCam->rightHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, addPersonForm, &AddPersonForm::drawIrisImageOnFrame); + // 初始化电机控制 + ProMemory::getInstance().moto = new MotoController(this); + ProMemory::getInstance().moto->initSerialMCU(); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::motoControl, + ProMemory::getInstance().moto, &MotoController::autoPosition); + // 打印日志 LOG(INFO) << QString("应用程序启动成功[Application Startup Success]").toStdString(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::MAIN_PAGE; @@ -72,6 +79,10 @@ ProMemory::getInstance().irisRecogPro->deleteLater(); ProMemory::getInstance().irisRecogPro->wait(); + ProMemory::getInstance().camPosCtrl->exitThread(); + ProMemory::getInstance().camPosCtrl->deleteLater(); + ProMemory::getInstance().camPosCtrl->wait(); + // 关闭自动启动的外部程序 // outExe->close(); // delete outExe; @@ -81,12 +92,14 @@ delete ProMemory::getInstance().faceRecogPro; delete ProMemory::getInstance().irisRegistPro; delete ProMemory::getInstance().irisRecogPro; + delete ProMemory::getInstance().camPosCtrl; } void CasicBioRecWin::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: + LOG(INFO) << "" << std::endl; QTimer::singleShot(100, qApp, SLOT(quit())); default: @@ -204,8 +217,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -244,8 +255,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -255,3 +264,17 @@ ProMemory::getInstance().irisRecogPro->start(); } + +void CasicBioRecWin::initCameraPositionThread() +{ + // 调整相机位置处理 + ProMemory::getInstance().camPosCtrl = new CameraPositionController(this); + + // 绑定信号与槽函数 + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTips, + recogResultForm, &RecognizeResultForm::updateRecogTips); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTipsBackgroundColor, + recogResultForm, &RecognizeResultForm::updateRecogTipsColor); + + ProMemory::getInstance().camPosCtrl->start(); +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h index b70245a..b5a3db9 100644 --- a/CasicBioRecWin.h +++ b/CasicBioRecWin.h @@ -54,6 +54,7 @@ void initFaceRecogThread(); void initIrisRegistThread(); void initIrisRecogThread(); + void initCameraPositionThread(); }; #endif // CASICBIORECWIN_H diff --git a/RecognizeResultForm.cpp b/RecognizeResultForm.cpp index e45a191..b340be9 100644 --- a/RecognizeResultForm.cpp +++ b/RecognizeResultForm.cpp @@ -20,7 +20,7 @@ RecognizeResultForm::~RecognizeResultForm() { - delete ui; + delete ui; } void RecognizeResultForm::startWorkingRecognize() @@ -29,23 +29,32 @@ switch (SettingConfig::getInstance().RECOG_TYPE) { case 1: // 人脸识别 + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); break; case 2: // 虹膜识别 + ProMemory::getInstance().clearIrisQueue(); +// ProMemory::getInstance().camPosCtrl->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; case 3: + // 双认证 先打开人脸识别 成功后再进行虹膜识别 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(true); + break; case 4: // 人脸和虹膜都需要打开 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; } - // 将界面切换到识别界面 RecognizeResultForm + // 开始拍图并显示视频 ProMemory::getInstance().faceCam->openFaceCamera(SettingConfig::getInstance().FACE_FRAME_INTERVAL); ui->labBackground->raise(); @@ -80,6 +89,14 @@ ui->widgetFail->raise(); ui->widgetFail->show(); + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().camPosCtrl->setWorking(false); + + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(false); + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ ui->labBackground->raise(); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -137,9 +154,9 @@ case 1: { // 仅人脸识别 - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); LOG(DEBUG) << QString("[RecognizeResultForm] 人脸识别成功 [%1]").arg(CasicFaceRecState::getInstance().toString()).toStdString(); @@ -158,9 +175,12 @@ case 2: { // 仅虹膜识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + // 停止控制电机和提示 + ProMemory::getInstance().camPosCtrl->setWorking(false); LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜识别成功 [%1]").arg(CasicIrisRecState::getInstance().toString()).toStdString(); @@ -179,13 +199,13 @@ case 4: { // 任意识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); QString logStr = QString("[RecognizeResultForm]%1识别成功[%2]"); if (faceOrIris == 1) @@ -213,42 +233,56 @@ if (faceOrIris == 1) { this->personIdByFace = personId; + + // 人脸识别成功后 开始进行虹膜识别 + // 1. 首先停止人脸识别 + ProMemory::getInstance().faceRecogPro->setWorking(false); + ProMemory::getInstance().clearFaceQueue(); + + // 2. 虹膜识别开始 + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().camPosCtrl->setWorking(true); } else if (faceOrIris == 2) { this->personIdByIris = personId; + + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) + { + // 只有一个成功的结果 需要等待下次 + return; + } else if (personIdByFace != personIdByIris) + { + // 人脸和虹膜识别的不是同一人 识别失败 + LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); + SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); + showRecogFailure(); + } else + { + LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); + showRecognizeResult(personId); + + // 识别记录存入数据库 + RecognitionRecordDao recDao; + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("type", "3"); + record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); + recDao.save(record); + } } - - if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) - { - // 只有一个成功的结果 需要等待下次 - return; - } else if (personIdByFace != personIdByIris) - { - // 人脸和虹膜识别的不是同一人 识别失败 - LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); - SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); - showRecogFailure(); - } else - { - LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); - showRecognizeResult(personId); - } - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - ProMemory::getInstance().clearFaceQueue(); - ProMemory::getInstance().faceRecogPro->setWorking(false); - ProMemory::getInstance().faceCam->stopTakingPhoto(); - - // 识别记录存入数据库 - RecognitionRecordDao recDao; - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("type", "4"); - record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); - recDao.save(record); } } + +void RecognizeResultForm::updateRecogTips(QString tipsText) +{ + ui->labTitle->setText(tipsText); +} +void RecognizeResultForm::updateRecogTipsColor(QString bgColor) +{ + ui->labTitle->setStyleSheet("background: " + bgColor); +} diff --git a/RecognizeResultForm.h b/RecognizeResultForm.h index 2c51865..65dd8ad 100644 --- a/RecognizeResultForm.h +++ b/RecognizeResultForm.h @@ -30,6 +30,8 @@ void startWorkingRecognize(); // 开始工作 void drawImageOnHomeForm(QImage imageDisp); + void updateRecogTips(QString tipsText); + void updateRecogTipsColor(QString bgColor); private: Ui::RecognizeResultForm *ui; diff --git a/StartupForm.cpp b/StartupForm.cpp index 16c4dfc..cf20de1 100644 --- a/StartupForm.cpp +++ b/StartupForm.cpp @@ -20,17 +20,23 @@ } // 设置弹簧的高度和宽度 - ui->vsTop->changeSize(0, 200); - ui->vsMidd->changeSize(0, 100); ui->hsLeft->changeSize(400, 0); ui->hsMidd->changeSize(150, 0); + // 绑定时间和日期的标签单击事件 单击即开始识别 + connect(ui->labDate, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + connect(ui->labTime, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + // 初始化更新界面的定时器 // 每秒执行一次 connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &StartupForm::updateDateAndTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, - this, &StartupForm::takeOneFrameForCheckStatus); +// connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, +// this, &StartupForm::takeOneFrameForCheckStatus); TimeCounterUtil::getInstance().clockCounter->start(1000); } diff --git a/StartupForm.h b/StartupForm.h index f2850e9..fc79be0 100644 --- a/StartupForm.h +++ b/StartupForm.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "casic/ProMemory.h" #include "utils/UtilInclude.h" diff --git a/StartupForm.ui b/StartupForm.ui index afb610f..de353f3 100644 --- a/StartupForm.ui +++ b/StartupForm.ui @@ -15,20 +15,7 @@ - - - Qt::Vertical - - - - 17 - 166 - - - - - - + TextLabel @@ -38,7 +25,7 @@ - + TextLabel @@ -48,19 +35,6 @@ - - - Qt::Vertical - - - - 17 - 167 - - - - - @@ -158,6 +132,13 @@ + + + QDblClickLabel + QLabel +
QDblClickLabel.h
+
+
diff --git a/casic/ProMemory.h b/casic/ProMemory.h index 3e9fbd4..02a14cf 100644 --- a/casic/ProMemory.h +++ b/casic/ProMemory.h @@ -16,6 +16,8 @@ #include "device/face/FaceRecogProcess.h" #include "device/iris/IrisRegistProcess.h" #include "device/iris/IrisRecogProcess.h" +#include "device/MotoController.h" +#include "device/CameraPositionController.h" class FaceCameraController; class IrisCameraController; @@ -23,6 +25,8 @@ class FaceRecogProcess; class IrisRegistProcess; class IrisRecogProcess; +class MotoController; +class CameraPositionController; class ProMemory { @@ -66,6 +70,10 @@ IrisRegistProcess * irisRegistPro; IrisRecogProcess * irisRecogPro; + MotoController * moto; + + CameraPositionController * camPosCtrl; + private: ProMemory(); diff --git a/casic/face/CasicFaceInterface.cpp b/casic/face/CasicFaceInterface.cpp index f530212..3cb2118 100644 --- a/casic/face/CasicFaceInterface.cpp +++ b/casic/face/CasicFaceInterface.cpp @@ -45,8 +45,6 @@ delete this->cascade; this->cascade = nullptr; } - - LOG(DEBUG) << "delete models in destructor"; } void casic::face::CasicFaceInterface::setDetectorModelPath(std::string detectorModelPath) @@ -384,6 +382,9 @@ cv::Size minRectSize(minFaceSize, minFaceSize); cv::Size maxRectSize(maxFaceSize, maxFaceSize); + QElapsedTimer timer; + timer.start(); + // ★分类器对象调用 cascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); @@ -391,6 +392,8 @@ { return cv::Rect(0, 0, 0, 0); } + + LOG(DEBUG) << QString("人脸分类检测算法[tm: %1 ms][%2, %3]").arg(timer.elapsed()).arg(rect.at(0).width).arg(rect.at(0).height).toStdString(); return rect.at(0); } @@ -424,7 +427,7 @@ return rect.at(0); } -bool casic::face::CasicFaceInterface::hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize) +std::vector casic::face::CasicFaceInterface::eyeDetectByCVCascade(cv::Mat frame, int minEyeSize) { // 构建openCV自带的眼睛分类器 if (this->eyeCascade == nullptr) @@ -433,14 +436,14 @@ this->eyeCascade->load(cvEyeCascadeName); } - std::vector rect; + std::vector rectVec; cv::Size minRectSize(minEyeSize, minEyeSize); cv::Size maxRectSize(maxEyeSize, maxEyeSize); // ★分类器对象调用 - eyeCascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); + eyeCascade->detectMultiScale(frame, rectVec, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); - return rect.size() == 0 ? false : true; + return rectVec; } void casic::face::CasicFaceInterface::setMinFaceSize(int minFaceSize) diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp index f202cfe..bc8018b 100644 --- a/CasicBioRecWin.cpp +++ b/CasicBioRecWin.cpp @@ -6,7 +6,7 @@ , ui(new Ui::CasicBioRecWin) { // 打开外部可执行程序 - outExe = new QProcess(this); +// outExe = new QProcess(this); // outExe->start(SettingConfig::getInstance().OUT_EXE_FILE); ui->setupUi(this); @@ -31,6 +31,7 @@ initFaceRecogThread(); // 人脸识别线程 initIrisRegistThread(); // 虹膜注册线程 initIrisRecogThread(); // 虹膜识别线程 + initCameraPositionThread(); // 调整相机位置 // 初始化人脸相机控制 ProMemory::getInstance().faceCam = new FaceCameraController(this); @@ -49,6 +50,12 @@ connect(ProMemory::getInstance().irisCam->rightHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, addPersonForm, &AddPersonForm::drawIrisImageOnFrame); + // 初始化电机控制 + ProMemory::getInstance().moto = new MotoController(this); + ProMemory::getInstance().moto->initSerialMCU(); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::motoControl, + ProMemory::getInstance().moto, &MotoController::autoPosition); + // 打印日志 LOG(INFO) << QString("应用程序启动成功[Application Startup Success]").toStdString(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::MAIN_PAGE; @@ -72,6 +79,10 @@ ProMemory::getInstance().irisRecogPro->deleteLater(); ProMemory::getInstance().irisRecogPro->wait(); + ProMemory::getInstance().camPosCtrl->exitThread(); + ProMemory::getInstance().camPosCtrl->deleteLater(); + ProMemory::getInstance().camPosCtrl->wait(); + // 关闭自动启动的外部程序 // outExe->close(); // delete outExe; @@ -81,12 +92,14 @@ delete ProMemory::getInstance().faceRecogPro; delete ProMemory::getInstance().irisRegistPro; delete ProMemory::getInstance().irisRecogPro; + delete ProMemory::getInstance().camPosCtrl; } void CasicBioRecWin::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: + LOG(INFO) << "" << std::endl; QTimer::singleShot(100, qApp, SLOT(quit())); default: @@ -204,8 +217,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -244,8 +255,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -255,3 +264,17 @@ ProMemory::getInstance().irisRecogPro->start(); } + +void CasicBioRecWin::initCameraPositionThread() +{ + // 调整相机位置处理 + ProMemory::getInstance().camPosCtrl = new CameraPositionController(this); + + // 绑定信号与槽函数 + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTips, + recogResultForm, &RecognizeResultForm::updateRecogTips); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTipsBackgroundColor, + recogResultForm, &RecognizeResultForm::updateRecogTipsColor); + + ProMemory::getInstance().camPosCtrl->start(); +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h index b70245a..b5a3db9 100644 --- a/CasicBioRecWin.h +++ b/CasicBioRecWin.h @@ -54,6 +54,7 @@ void initFaceRecogThread(); void initIrisRegistThread(); void initIrisRecogThread(); + void initCameraPositionThread(); }; #endif // CASICBIORECWIN_H diff --git a/RecognizeResultForm.cpp b/RecognizeResultForm.cpp index e45a191..b340be9 100644 --- a/RecognizeResultForm.cpp +++ b/RecognizeResultForm.cpp @@ -20,7 +20,7 @@ RecognizeResultForm::~RecognizeResultForm() { - delete ui; + delete ui; } void RecognizeResultForm::startWorkingRecognize() @@ -29,23 +29,32 @@ switch (SettingConfig::getInstance().RECOG_TYPE) { case 1: // 人脸识别 + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); break; case 2: // 虹膜识别 + ProMemory::getInstance().clearIrisQueue(); +// ProMemory::getInstance().camPosCtrl->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; case 3: + // 双认证 先打开人脸识别 成功后再进行虹膜识别 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(true); + break; case 4: // 人脸和虹膜都需要打开 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; } - // 将界面切换到识别界面 RecognizeResultForm + // 开始拍图并显示视频 ProMemory::getInstance().faceCam->openFaceCamera(SettingConfig::getInstance().FACE_FRAME_INTERVAL); ui->labBackground->raise(); @@ -80,6 +89,14 @@ ui->widgetFail->raise(); ui->widgetFail->show(); + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().camPosCtrl->setWorking(false); + + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(false); + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ ui->labBackground->raise(); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -137,9 +154,9 @@ case 1: { // 仅人脸识别 - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); LOG(DEBUG) << QString("[RecognizeResultForm] 人脸识别成功 [%1]").arg(CasicFaceRecState::getInstance().toString()).toStdString(); @@ -158,9 +175,12 @@ case 2: { // 仅虹膜识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + // 停止控制电机和提示 + ProMemory::getInstance().camPosCtrl->setWorking(false); LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜识别成功 [%1]").arg(CasicIrisRecState::getInstance().toString()).toStdString(); @@ -179,13 +199,13 @@ case 4: { // 任意识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); QString logStr = QString("[RecognizeResultForm]%1识别成功[%2]"); if (faceOrIris == 1) @@ -213,42 +233,56 @@ if (faceOrIris == 1) { this->personIdByFace = personId; + + // 人脸识别成功后 开始进行虹膜识别 + // 1. 首先停止人脸识别 + ProMemory::getInstance().faceRecogPro->setWorking(false); + ProMemory::getInstance().clearFaceQueue(); + + // 2. 虹膜识别开始 + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().camPosCtrl->setWorking(true); } else if (faceOrIris == 2) { this->personIdByIris = personId; + + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) + { + // 只有一个成功的结果 需要等待下次 + return; + } else if (personIdByFace != personIdByIris) + { + // 人脸和虹膜识别的不是同一人 识别失败 + LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); + SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); + showRecogFailure(); + } else + { + LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); + showRecognizeResult(personId); + + // 识别记录存入数据库 + RecognitionRecordDao recDao; + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("type", "3"); + record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); + recDao.save(record); + } } - - if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) - { - // 只有一个成功的结果 需要等待下次 - return; - } else if (personIdByFace != personIdByIris) - { - // 人脸和虹膜识别的不是同一人 识别失败 - LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); - SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); - showRecogFailure(); - } else - { - LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); - showRecognizeResult(personId); - } - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - ProMemory::getInstance().clearFaceQueue(); - ProMemory::getInstance().faceRecogPro->setWorking(false); - ProMemory::getInstance().faceCam->stopTakingPhoto(); - - // 识别记录存入数据库 - RecognitionRecordDao recDao; - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("type", "4"); - record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); - recDao.save(record); } } + +void RecognizeResultForm::updateRecogTips(QString tipsText) +{ + ui->labTitle->setText(tipsText); +} +void RecognizeResultForm::updateRecogTipsColor(QString bgColor) +{ + ui->labTitle->setStyleSheet("background: " + bgColor); +} diff --git a/RecognizeResultForm.h b/RecognizeResultForm.h index 2c51865..65dd8ad 100644 --- a/RecognizeResultForm.h +++ b/RecognizeResultForm.h @@ -30,6 +30,8 @@ void startWorkingRecognize(); // 开始工作 void drawImageOnHomeForm(QImage imageDisp); + void updateRecogTips(QString tipsText); + void updateRecogTipsColor(QString bgColor); private: Ui::RecognizeResultForm *ui; diff --git a/StartupForm.cpp b/StartupForm.cpp index 16c4dfc..cf20de1 100644 --- a/StartupForm.cpp +++ b/StartupForm.cpp @@ -20,17 +20,23 @@ } // 设置弹簧的高度和宽度 - ui->vsTop->changeSize(0, 200); - ui->vsMidd->changeSize(0, 100); ui->hsLeft->changeSize(400, 0); ui->hsMidd->changeSize(150, 0); + // 绑定时间和日期的标签单击事件 单击即开始识别 + connect(ui->labDate, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + connect(ui->labTime, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + // 初始化更新界面的定时器 // 每秒执行一次 connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &StartupForm::updateDateAndTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, - this, &StartupForm::takeOneFrameForCheckStatus); +// connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, +// this, &StartupForm::takeOneFrameForCheckStatus); TimeCounterUtil::getInstance().clockCounter->start(1000); } diff --git a/StartupForm.h b/StartupForm.h index f2850e9..fc79be0 100644 --- a/StartupForm.h +++ b/StartupForm.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "casic/ProMemory.h" #include "utils/UtilInclude.h" diff --git a/StartupForm.ui b/StartupForm.ui index afb610f..de353f3 100644 --- a/StartupForm.ui +++ b/StartupForm.ui @@ -15,20 +15,7 @@ - - - Qt::Vertical - - - - 17 - 166 - - - - - - + TextLabel @@ -38,7 +25,7 @@ - + TextLabel @@ -48,19 +35,6 @@ - - - Qt::Vertical - - - - 17 - 167 - - - - - @@ -158,6 +132,13 @@ + + + QDblClickLabel + QLabel +
QDblClickLabel.h
+
+
diff --git a/casic/ProMemory.h b/casic/ProMemory.h index 3e9fbd4..02a14cf 100644 --- a/casic/ProMemory.h +++ b/casic/ProMemory.h @@ -16,6 +16,8 @@ #include "device/face/FaceRecogProcess.h" #include "device/iris/IrisRegistProcess.h" #include "device/iris/IrisRecogProcess.h" +#include "device/MotoController.h" +#include "device/CameraPositionController.h" class FaceCameraController; class IrisCameraController; @@ -23,6 +25,8 @@ class FaceRecogProcess; class IrisRegistProcess; class IrisRecogProcess; +class MotoController; +class CameraPositionController; class ProMemory { @@ -66,6 +70,10 @@ IrisRegistProcess * irisRegistPro; IrisRecogProcess * irisRecogPro; + MotoController * moto; + + CameraPositionController * camPosCtrl; + private: ProMemory(); diff --git a/casic/face/CasicFaceInterface.cpp b/casic/face/CasicFaceInterface.cpp index f530212..3cb2118 100644 --- a/casic/face/CasicFaceInterface.cpp +++ b/casic/face/CasicFaceInterface.cpp @@ -45,8 +45,6 @@ delete this->cascade; this->cascade = nullptr; } - - LOG(DEBUG) << "delete models in destructor"; } void casic::face::CasicFaceInterface::setDetectorModelPath(std::string detectorModelPath) @@ -384,6 +382,9 @@ cv::Size minRectSize(minFaceSize, minFaceSize); cv::Size maxRectSize(maxFaceSize, maxFaceSize); + QElapsedTimer timer; + timer.start(); + // ★分类器对象调用 cascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); @@ -391,6 +392,8 @@ { return cv::Rect(0, 0, 0, 0); } + + LOG(DEBUG) << QString("人脸分类检测算法[tm: %1 ms][%2, %3]").arg(timer.elapsed()).arg(rect.at(0).width).arg(rect.at(0).height).toStdString(); return rect.at(0); } @@ -424,7 +427,7 @@ return rect.at(0); } -bool casic::face::CasicFaceInterface::hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize) +std::vector casic::face::CasicFaceInterface::eyeDetectByCVCascade(cv::Mat frame, int minEyeSize) { // 构建openCV自带的眼睛分类器 if (this->eyeCascade == nullptr) @@ -433,14 +436,14 @@ this->eyeCascade->load(cvEyeCascadeName); } - std::vector rect; + std::vector rectVec; cv::Size minRectSize(minEyeSize, minEyeSize); cv::Size maxRectSize(maxEyeSize, maxEyeSize); // ★分类器对象调用 - eyeCascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); + eyeCascade->detectMultiScale(frame, rectVec, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); - return rect.size() == 0 ? false : true; + return rectVec; } void casic::face::CasicFaceInterface::setMinFaceSize(int minFaceSize) diff --git a/casic/face/CasicFaceInterface.h b/casic/face/CasicFaceInterface.h index 9d8b8ea..1753bd1 100644 --- a/casic/face/CasicFaceInterface.h +++ b/casic/face/CasicFaceInterface.h @@ -52,7 +52,7 @@ cv::Rect faceDetectByCVCascade(cv::Mat frame, int minFaceSize); cv::Rect eyeDetectByCVCascade(cv::Mat frame); - bool hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize); + std::vector eyeDetectByCVCascade(cv::Mat frame, int minEyeSize); void setMinFaceSize(int minFaceSize); void setMinEyeSize(int minEyeSize); private: diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp index f202cfe..bc8018b 100644 --- a/CasicBioRecWin.cpp +++ b/CasicBioRecWin.cpp @@ -6,7 +6,7 @@ , ui(new Ui::CasicBioRecWin) { // 打开外部可执行程序 - outExe = new QProcess(this); +// outExe = new QProcess(this); // outExe->start(SettingConfig::getInstance().OUT_EXE_FILE); ui->setupUi(this); @@ -31,6 +31,7 @@ initFaceRecogThread(); // 人脸识别线程 initIrisRegistThread(); // 虹膜注册线程 initIrisRecogThread(); // 虹膜识别线程 + initCameraPositionThread(); // 调整相机位置 // 初始化人脸相机控制 ProMemory::getInstance().faceCam = new FaceCameraController(this); @@ -49,6 +50,12 @@ connect(ProMemory::getInstance().irisCam->rightHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, addPersonForm, &AddPersonForm::drawIrisImageOnFrame); + // 初始化电机控制 + ProMemory::getInstance().moto = new MotoController(this); + ProMemory::getInstance().moto->initSerialMCU(); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::motoControl, + ProMemory::getInstance().moto, &MotoController::autoPosition); + // 打印日志 LOG(INFO) << QString("应用程序启动成功[Application Startup Success]").toStdString(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::MAIN_PAGE; @@ -72,6 +79,10 @@ ProMemory::getInstance().irisRecogPro->deleteLater(); ProMemory::getInstance().irisRecogPro->wait(); + ProMemory::getInstance().camPosCtrl->exitThread(); + ProMemory::getInstance().camPosCtrl->deleteLater(); + ProMemory::getInstance().camPosCtrl->wait(); + // 关闭自动启动的外部程序 // outExe->close(); // delete outExe; @@ -81,12 +92,14 @@ delete ProMemory::getInstance().faceRecogPro; delete ProMemory::getInstance().irisRegistPro; delete ProMemory::getInstance().irisRecogPro; + delete ProMemory::getInstance().camPosCtrl; } void CasicBioRecWin::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: + LOG(INFO) << "" << std::endl; QTimer::singleShot(100, qApp, SLOT(quit())); default: @@ -204,8 +217,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -244,8 +255,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -255,3 +264,17 @@ ProMemory::getInstance().irisRecogPro->start(); } + +void CasicBioRecWin::initCameraPositionThread() +{ + // 调整相机位置处理 + ProMemory::getInstance().camPosCtrl = new CameraPositionController(this); + + // 绑定信号与槽函数 + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTips, + recogResultForm, &RecognizeResultForm::updateRecogTips); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTipsBackgroundColor, + recogResultForm, &RecognizeResultForm::updateRecogTipsColor); + + ProMemory::getInstance().camPosCtrl->start(); +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h index b70245a..b5a3db9 100644 --- a/CasicBioRecWin.h +++ b/CasicBioRecWin.h @@ -54,6 +54,7 @@ void initFaceRecogThread(); void initIrisRegistThread(); void initIrisRecogThread(); + void initCameraPositionThread(); }; #endif // CASICBIORECWIN_H diff --git a/RecognizeResultForm.cpp b/RecognizeResultForm.cpp index e45a191..b340be9 100644 --- a/RecognizeResultForm.cpp +++ b/RecognizeResultForm.cpp @@ -20,7 +20,7 @@ RecognizeResultForm::~RecognizeResultForm() { - delete ui; + delete ui; } void RecognizeResultForm::startWorkingRecognize() @@ -29,23 +29,32 @@ switch (SettingConfig::getInstance().RECOG_TYPE) { case 1: // 人脸识别 + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); break; case 2: // 虹膜识别 + ProMemory::getInstance().clearIrisQueue(); +// ProMemory::getInstance().camPosCtrl->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; case 3: + // 双认证 先打开人脸识别 成功后再进行虹膜识别 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(true); + break; case 4: // 人脸和虹膜都需要打开 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; } - // 将界面切换到识别界面 RecognizeResultForm + // 开始拍图并显示视频 ProMemory::getInstance().faceCam->openFaceCamera(SettingConfig::getInstance().FACE_FRAME_INTERVAL); ui->labBackground->raise(); @@ -80,6 +89,14 @@ ui->widgetFail->raise(); ui->widgetFail->show(); + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().camPosCtrl->setWorking(false); + + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(false); + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ ui->labBackground->raise(); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -137,9 +154,9 @@ case 1: { // 仅人脸识别 - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); LOG(DEBUG) << QString("[RecognizeResultForm] 人脸识别成功 [%1]").arg(CasicFaceRecState::getInstance().toString()).toStdString(); @@ -158,9 +175,12 @@ case 2: { // 仅虹膜识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + // 停止控制电机和提示 + ProMemory::getInstance().camPosCtrl->setWorking(false); LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜识别成功 [%1]").arg(CasicIrisRecState::getInstance().toString()).toStdString(); @@ -179,13 +199,13 @@ case 4: { // 任意识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); QString logStr = QString("[RecognizeResultForm]%1识别成功[%2]"); if (faceOrIris == 1) @@ -213,42 +233,56 @@ if (faceOrIris == 1) { this->personIdByFace = personId; + + // 人脸识别成功后 开始进行虹膜识别 + // 1. 首先停止人脸识别 + ProMemory::getInstance().faceRecogPro->setWorking(false); + ProMemory::getInstance().clearFaceQueue(); + + // 2. 虹膜识别开始 + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().camPosCtrl->setWorking(true); } else if (faceOrIris == 2) { this->personIdByIris = personId; + + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) + { + // 只有一个成功的结果 需要等待下次 + return; + } else if (personIdByFace != personIdByIris) + { + // 人脸和虹膜识别的不是同一人 识别失败 + LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); + SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); + showRecogFailure(); + } else + { + LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); + showRecognizeResult(personId); + + // 识别记录存入数据库 + RecognitionRecordDao recDao; + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("type", "3"); + record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); + recDao.save(record); + } } - - if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) - { - // 只有一个成功的结果 需要等待下次 - return; - } else if (personIdByFace != personIdByIris) - { - // 人脸和虹膜识别的不是同一人 识别失败 - LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); - SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); - showRecogFailure(); - } else - { - LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); - showRecognizeResult(personId); - } - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - ProMemory::getInstance().clearFaceQueue(); - ProMemory::getInstance().faceRecogPro->setWorking(false); - ProMemory::getInstance().faceCam->stopTakingPhoto(); - - // 识别记录存入数据库 - RecognitionRecordDao recDao; - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("type", "4"); - record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); - recDao.save(record); } } + +void RecognizeResultForm::updateRecogTips(QString tipsText) +{ + ui->labTitle->setText(tipsText); +} +void RecognizeResultForm::updateRecogTipsColor(QString bgColor) +{ + ui->labTitle->setStyleSheet("background: " + bgColor); +} diff --git a/RecognizeResultForm.h b/RecognizeResultForm.h index 2c51865..65dd8ad 100644 --- a/RecognizeResultForm.h +++ b/RecognizeResultForm.h @@ -30,6 +30,8 @@ void startWorkingRecognize(); // 开始工作 void drawImageOnHomeForm(QImage imageDisp); + void updateRecogTips(QString tipsText); + void updateRecogTipsColor(QString bgColor); private: Ui::RecognizeResultForm *ui; diff --git a/StartupForm.cpp b/StartupForm.cpp index 16c4dfc..cf20de1 100644 --- a/StartupForm.cpp +++ b/StartupForm.cpp @@ -20,17 +20,23 @@ } // 设置弹簧的高度和宽度 - ui->vsTop->changeSize(0, 200); - ui->vsMidd->changeSize(0, 100); ui->hsLeft->changeSize(400, 0); ui->hsMidd->changeSize(150, 0); + // 绑定时间和日期的标签单击事件 单击即开始识别 + connect(ui->labDate, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + connect(ui->labTime, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + // 初始化更新界面的定时器 // 每秒执行一次 connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &StartupForm::updateDateAndTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, - this, &StartupForm::takeOneFrameForCheckStatus); +// connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, +// this, &StartupForm::takeOneFrameForCheckStatus); TimeCounterUtil::getInstance().clockCounter->start(1000); } diff --git a/StartupForm.h b/StartupForm.h index f2850e9..fc79be0 100644 --- a/StartupForm.h +++ b/StartupForm.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "casic/ProMemory.h" #include "utils/UtilInclude.h" diff --git a/StartupForm.ui b/StartupForm.ui index afb610f..de353f3 100644 --- a/StartupForm.ui +++ b/StartupForm.ui @@ -15,20 +15,7 @@ - - - Qt::Vertical - - - - 17 - 166 - - - - - - + TextLabel @@ -38,7 +25,7 @@ - + TextLabel @@ -48,19 +35,6 @@ - - - Qt::Vertical - - - - 17 - 167 - - - - - @@ -158,6 +132,13 @@ + + + QDblClickLabel + QLabel +
QDblClickLabel.h
+
+
diff --git a/casic/ProMemory.h b/casic/ProMemory.h index 3e9fbd4..02a14cf 100644 --- a/casic/ProMemory.h +++ b/casic/ProMemory.h @@ -16,6 +16,8 @@ #include "device/face/FaceRecogProcess.h" #include "device/iris/IrisRegistProcess.h" #include "device/iris/IrisRecogProcess.h" +#include "device/MotoController.h" +#include "device/CameraPositionController.h" class FaceCameraController; class IrisCameraController; @@ -23,6 +25,8 @@ class FaceRecogProcess; class IrisRegistProcess; class IrisRecogProcess; +class MotoController; +class CameraPositionController; class ProMemory { @@ -66,6 +70,10 @@ IrisRegistProcess * irisRegistPro; IrisRecogProcess * irisRecogPro; + MotoController * moto; + + CameraPositionController * camPosCtrl; + private: ProMemory(); diff --git a/casic/face/CasicFaceInterface.cpp b/casic/face/CasicFaceInterface.cpp index f530212..3cb2118 100644 --- a/casic/face/CasicFaceInterface.cpp +++ b/casic/face/CasicFaceInterface.cpp @@ -45,8 +45,6 @@ delete this->cascade; this->cascade = nullptr; } - - LOG(DEBUG) << "delete models in destructor"; } void casic::face::CasicFaceInterface::setDetectorModelPath(std::string detectorModelPath) @@ -384,6 +382,9 @@ cv::Size minRectSize(minFaceSize, minFaceSize); cv::Size maxRectSize(maxFaceSize, maxFaceSize); + QElapsedTimer timer; + timer.start(); + // ★分类器对象调用 cascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); @@ -391,6 +392,8 @@ { return cv::Rect(0, 0, 0, 0); } + + LOG(DEBUG) << QString("人脸分类检测算法[tm: %1 ms][%2, %3]").arg(timer.elapsed()).arg(rect.at(0).width).arg(rect.at(0).height).toStdString(); return rect.at(0); } @@ -424,7 +427,7 @@ return rect.at(0); } -bool casic::face::CasicFaceInterface::hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize) +std::vector casic::face::CasicFaceInterface::eyeDetectByCVCascade(cv::Mat frame, int minEyeSize) { // 构建openCV自带的眼睛分类器 if (this->eyeCascade == nullptr) @@ -433,14 +436,14 @@ this->eyeCascade->load(cvEyeCascadeName); } - std::vector rect; + std::vector rectVec; cv::Size minRectSize(minEyeSize, minEyeSize); cv::Size maxRectSize(maxEyeSize, maxEyeSize); // ★分类器对象调用 - eyeCascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); + eyeCascade->detectMultiScale(frame, rectVec, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); - return rect.size() == 0 ? false : true; + return rectVec; } void casic::face::CasicFaceInterface::setMinFaceSize(int minFaceSize) diff --git a/casic/face/CasicFaceInterface.h b/casic/face/CasicFaceInterface.h index 9d8b8ea..1753bd1 100644 --- a/casic/face/CasicFaceInterface.h +++ b/casic/face/CasicFaceInterface.h @@ -52,7 +52,7 @@ cv::Rect faceDetectByCVCascade(cv::Mat frame, int minFaceSize); cv::Rect eyeDetectByCVCascade(cv::Mat frame); - bool hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize); + std::vector eyeDetectByCVCascade(cv::Mat frame, int minEyeSize); void setMinFaceSize(int minFaceSize); void setMinEyeSize(int minEyeSize); private: diff --git a/dao/RecognitionRecordDao.cpp b/dao/RecognitionRecordDao.cpp index 403894a..d7103f9 100644 --- a/dao/RecognitionRecordDao.cpp +++ b/dao/RecognitionRecordDao.cpp @@ -91,13 +91,14 @@ .arg(object.value("type").toString()) .arg(object.value("dev_code").toString()) .arg(object.value("door_code").toString()) - .arg(object.value("inout_type").toString()); + .arg(object.value("inout_type").toString()) + .arg(object.value("debug_info").toString()); query.prepare(sql); LOG(DEBUG) << sql.toStdString(); // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES ('%1', '%2')") + QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES ('%1', '%2')") .arg(id).arg(object.value("debug_info").toString()); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp index f202cfe..bc8018b 100644 --- a/CasicBioRecWin.cpp +++ b/CasicBioRecWin.cpp @@ -6,7 +6,7 @@ , ui(new Ui::CasicBioRecWin) { // 打开外部可执行程序 - outExe = new QProcess(this); +// outExe = new QProcess(this); // outExe->start(SettingConfig::getInstance().OUT_EXE_FILE); ui->setupUi(this); @@ -31,6 +31,7 @@ initFaceRecogThread(); // 人脸识别线程 initIrisRegistThread(); // 虹膜注册线程 initIrisRecogThread(); // 虹膜识别线程 + initCameraPositionThread(); // 调整相机位置 // 初始化人脸相机控制 ProMemory::getInstance().faceCam = new FaceCameraController(this); @@ -49,6 +50,12 @@ connect(ProMemory::getInstance().irisCam->rightHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, addPersonForm, &AddPersonForm::drawIrisImageOnFrame); + // 初始化电机控制 + ProMemory::getInstance().moto = new MotoController(this); + ProMemory::getInstance().moto->initSerialMCU(); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::motoControl, + ProMemory::getInstance().moto, &MotoController::autoPosition); + // 打印日志 LOG(INFO) << QString("应用程序启动成功[Application Startup Success]").toStdString(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::MAIN_PAGE; @@ -72,6 +79,10 @@ ProMemory::getInstance().irisRecogPro->deleteLater(); ProMemory::getInstance().irisRecogPro->wait(); + ProMemory::getInstance().camPosCtrl->exitThread(); + ProMemory::getInstance().camPosCtrl->deleteLater(); + ProMemory::getInstance().camPosCtrl->wait(); + // 关闭自动启动的外部程序 // outExe->close(); // delete outExe; @@ -81,12 +92,14 @@ delete ProMemory::getInstance().faceRecogPro; delete ProMemory::getInstance().irisRegistPro; delete ProMemory::getInstance().irisRecogPro; + delete ProMemory::getInstance().camPosCtrl; } void CasicBioRecWin::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: + LOG(INFO) << "" << std::endl; QTimer::singleShot(100, qApp, SLOT(quit())); default: @@ -204,8 +217,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -244,8 +255,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -255,3 +264,17 @@ ProMemory::getInstance().irisRecogPro->start(); } + +void CasicBioRecWin::initCameraPositionThread() +{ + // 调整相机位置处理 + ProMemory::getInstance().camPosCtrl = new CameraPositionController(this); + + // 绑定信号与槽函数 + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTips, + recogResultForm, &RecognizeResultForm::updateRecogTips); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTipsBackgroundColor, + recogResultForm, &RecognizeResultForm::updateRecogTipsColor); + + ProMemory::getInstance().camPosCtrl->start(); +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h index b70245a..b5a3db9 100644 --- a/CasicBioRecWin.h +++ b/CasicBioRecWin.h @@ -54,6 +54,7 @@ void initFaceRecogThread(); void initIrisRegistThread(); void initIrisRecogThread(); + void initCameraPositionThread(); }; #endif // CASICBIORECWIN_H diff --git a/RecognizeResultForm.cpp b/RecognizeResultForm.cpp index e45a191..b340be9 100644 --- a/RecognizeResultForm.cpp +++ b/RecognizeResultForm.cpp @@ -20,7 +20,7 @@ RecognizeResultForm::~RecognizeResultForm() { - delete ui; + delete ui; } void RecognizeResultForm::startWorkingRecognize() @@ -29,23 +29,32 @@ switch (SettingConfig::getInstance().RECOG_TYPE) { case 1: // 人脸识别 + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); break; case 2: // 虹膜识别 + ProMemory::getInstance().clearIrisQueue(); +// ProMemory::getInstance().camPosCtrl->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; case 3: + // 双认证 先打开人脸识别 成功后再进行虹膜识别 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(true); + break; case 4: // 人脸和虹膜都需要打开 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; } - // 将界面切换到识别界面 RecognizeResultForm + // 开始拍图并显示视频 ProMemory::getInstance().faceCam->openFaceCamera(SettingConfig::getInstance().FACE_FRAME_INTERVAL); ui->labBackground->raise(); @@ -80,6 +89,14 @@ ui->widgetFail->raise(); ui->widgetFail->show(); + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().camPosCtrl->setWorking(false); + + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(false); + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ ui->labBackground->raise(); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -137,9 +154,9 @@ case 1: { // 仅人脸识别 - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); LOG(DEBUG) << QString("[RecognizeResultForm] 人脸识别成功 [%1]").arg(CasicFaceRecState::getInstance().toString()).toStdString(); @@ -158,9 +175,12 @@ case 2: { // 仅虹膜识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + // 停止控制电机和提示 + ProMemory::getInstance().camPosCtrl->setWorking(false); LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜识别成功 [%1]").arg(CasicIrisRecState::getInstance().toString()).toStdString(); @@ -179,13 +199,13 @@ case 4: { // 任意识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); QString logStr = QString("[RecognizeResultForm]%1识别成功[%2]"); if (faceOrIris == 1) @@ -213,42 +233,56 @@ if (faceOrIris == 1) { this->personIdByFace = personId; + + // 人脸识别成功后 开始进行虹膜识别 + // 1. 首先停止人脸识别 + ProMemory::getInstance().faceRecogPro->setWorking(false); + ProMemory::getInstance().clearFaceQueue(); + + // 2. 虹膜识别开始 + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().camPosCtrl->setWorking(true); } else if (faceOrIris == 2) { this->personIdByIris = personId; + + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) + { + // 只有一个成功的结果 需要等待下次 + return; + } else if (personIdByFace != personIdByIris) + { + // 人脸和虹膜识别的不是同一人 识别失败 + LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); + SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); + showRecogFailure(); + } else + { + LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); + showRecognizeResult(personId); + + // 识别记录存入数据库 + RecognitionRecordDao recDao; + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("type", "3"); + record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); + recDao.save(record); + } } - - if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) - { - // 只有一个成功的结果 需要等待下次 - return; - } else if (personIdByFace != personIdByIris) - { - // 人脸和虹膜识别的不是同一人 识别失败 - LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); - SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); - showRecogFailure(); - } else - { - LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); - showRecognizeResult(personId); - } - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - ProMemory::getInstance().clearFaceQueue(); - ProMemory::getInstance().faceRecogPro->setWorking(false); - ProMemory::getInstance().faceCam->stopTakingPhoto(); - - // 识别记录存入数据库 - RecognitionRecordDao recDao; - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("type", "4"); - record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); - recDao.save(record); } } + +void RecognizeResultForm::updateRecogTips(QString tipsText) +{ + ui->labTitle->setText(tipsText); +} +void RecognizeResultForm::updateRecogTipsColor(QString bgColor) +{ + ui->labTitle->setStyleSheet("background: " + bgColor); +} diff --git a/RecognizeResultForm.h b/RecognizeResultForm.h index 2c51865..65dd8ad 100644 --- a/RecognizeResultForm.h +++ b/RecognizeResultForm.h @@ -30,6 +30,8 @@ void startWorkingRecognize(); // 开始工作 void drawImageOnHomeForm(QImage imageDisp); + void updateRecogTips(QString tipsText); + void updateRecogTipsColor(QString bgColor); private: Ui::RecognizeResultForm *ui; diff --git a/StartupForm.cpp b/StartupForm.cpp index 16c4dfc..cf20de1 100644 --- a/StartupForm.cpp +++ b/StartupForm.cpp @@ -20,17 +20,23 @@ } // 设置弹簧的高度和宽度 - ui->vsTop->changeSize(0, 200); - ui->vsMidd->changeSize(0, 100); ui->hsLeft->changeSize(400, 0); ui->hsMidd->changeSize(150, 0); + // 绑定时间和日期的标签单击事件 单击即开始识别 + connect(ui->labDate, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + connect(ui->labTime, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + // 初始化更新界面的定时器 // 每秒执行一次 connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &StartupForm::updateDateAndTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, - this, &StartupForm::takeOneFrameForCheckStatus); +// connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, +// this, &StartupForm::takeOneFrameForCheckStatus); TimeCounterUtil::getInstance().clockCounter->start(1000); } diff --git a/StartupForm.h b/StartupForm.h index f2850e9..fc79be0 100644 --- a/StartupForm.h +++ b/StartupForm.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "casic/ProMemory.h" #include "utils/UtilInclude.h" diff --git a/StartupForm.ui b/StartupForm.ui index afb610f..de353f3 100644 --- a/StartupForm.ui +++ b/StartupForm.ui @@ -15,20 +15,7 @@ - - - Qt::Vertical - - - - 17 - 166 - - - - - - + TextLabel @@ -38,7 +25,7 @@ - + TextLabel @@ -48,19 +35,6 @@ - - - Qt::Vertical - - - - 17 - 167 - - - - - @@ -158,6 +132,13 @@ + + + QDblClickLabel + QLabel +
QDblClickLabel.h
+
+
diff --git a/casic/ProMemory.h b/casic/ProMemory.h index 3e9fbd4..02a14cf 100644 --- a/casic/ProMemory.h +++ b/casic/ProMemory.h @@ -16,6 +16,8 @@ #include "device/face/FaceRecogProcess.h" #include "device/iris/IrisRegistProcess.h" #include "device/iris/IrisRecogProcess.h" +#include "device/MotoController.h" +#include "device/CameraPositionController.h" class FaceCameraController; class IrisCameraController; @@ -23,6 +25,8 @@ class FaceRecogProcess; class IrisRegistProcess; class IrisRecogProcess; +class MotoController; +class CameraPositionController; class ProMemory { @@ -66,6 +70,10 @@ IrisRegistProcess * irisRegistPro; IrisRecogProcess * irisRecogPro; + MotoController * moto; + + CameraPositionController * camPosCtrl; + private: ProMemory(); diff --git a/casic/face/CasicFaceInterface.cpp b/casic/face/CasicFaceInterface.cpp index f530212..3cb2118 100644 --- a/casic/face/CasicFaceInterface.cpp +++ b/casic/face/CasicFaceInterface.cpp @@ -45,8 +45,6 @@ delete this->cascade; this->cascade = nullptr; } - - LOG(DEBUG) << "delete models in destructor"; } void casic::face::CasicFaceInterface::setDetectorModelPath(std::string detectorModelPath) @@ -384,6 +382,9 @@ cv::Size minRectSize(minFaceSize, minFaceSize); cv::Size maxRectSize(maxFaceSize, maxFaceSize); + QElapsedTimer timer; + timer.start(); + // ★分类器对象调用 cascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); @@ -391,6 +392,8 @@ { return cv::Rect(0, 0, 0, 0); } + + LOG(DEBUG) << QString("人脸分类检测算法[tm: %1 ms][%2, %3]").arg(timer.elapsed()).arg(rect.at(0).width).arg(rect.at(0).height).toStdString(); return rect.at(0); } @@ -424,7 +427,7 @@ return rect.at(0); } -bool casic::face::CasicFaceInterface::hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize) +std::vector casic::face::CasicFaceInterface::eyeDetectByCVCascade(cv::Mat frame, int minEyeSize) { // 构建openCV自带的眼睛分类器 if (this->eyeCascade == nullptr) @@ -433,14 +436,14 @@ this->eyeCascade->load(cvEyeCascadeName); } - std::vector rect; + std::vector rectVec; cv::Size minRectSize(minEyeSize, minEyeSize); cv::Size maxRectSize(maxEyeSize, maxEyeSize); // ★分类器对象调用 - eyeCascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); + eyeCascade->detectMultiScale(frame, rectVec, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); - return rect.size() == 0 ? false : true; + return rectVec; } void casic::face::CasicFaceInterface::setMinFaceSize(int minFaceSize) diff --git a/casic/face/CasicFaceInterface.h b/casic/face/CasicFaceInterface.h index 9d8b8ea..1753bd1 100644 --- a/casic/face/CasicFaceInterface.h +++ b/casic/face/CasicFaceInterface.h @@ -52,7 +52,7 @@ cv::Rect faceDetectByCVCascade(cv::Mat frame, int minFaceSize); cv::Rect eyeDetectByCVCascade(cv::Mat frame); - bool hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize); + std::vector eyeDetectByCVCascade(cv::Mat frame, int minEyeSize); void setMinFaceSize(int minFaceSize); void setMinEyeSize(int minEyeSize); private: diff --git a/dao/RecognitionRecordDao.cpp b/dao/RecognitionRecordDao.cpp index 403894a..d7103f9 100644 --- a/dao/RecognitionRecordDao.cpp +++ b/dao/RecognitionRecordDao.cpp @@ -91,13 +91,14 @@ .arg(object.value("type").toString()) .arg(object.value("dev_code").toString()) .arg(object.value("door_code").toString()) - .arg(object.value("inout_type").toString()); + .arg(object.value("inout_type").toString()) + .arg(object.value("debug_info").toString()); query.prepare(sql); LOG(DEBUG) << sql.toStdString(); // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES ('%1', '%2')") + QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES ('%1', '%2')") .arg(id).arg(object.value("debug_info").toString()); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/device/CameraPositionController.cpp b/device/CameraPositionController.cpp new file mode 100644 index 0000000..577c9ad --- /dev/null +++ b/device/CameraPositionController.cpp @@ -0,0 +1,91 @@ +#include "CameraPositionController.h" + +CameraPositionController::CameraPositionController(QObject *parent) : QThread(parent) +{ + this->working = false; + this->exit = false; +} + +CameraPositionController::~CameraPositionController() +{ + this->setWorking(false); +} + +void CameraPositionController::setWorking(bool working) +{ + this->working = working; +} +void CameraPositionController::exitThread() +{ + this->working = false; + this->exit = true; +} + +void CameraPositionController::run() +{ + while (exit == false) + { + if (this->working == false) + { + this->msleep(200); // 200ms后再判断 + continue; + } + + // 取一幅图像 + cv::Mat rawFrame = ProMemory::getInstance().faceCam->takeOneRawFrame(); +/* + // 分类器找眼睛 + cv::Rect eyeRect = casic::face::CasicFaceInterface::getInstance().eyeDetectByCVCascade(rawFrame); + if (eyeRect.width != 0) + { + // 眼睛的位置 + int eyeCenter = eyeRect.y + eyeRect.height / 2; + LOG(DEBUG) << eyeCenter << " " << abs(eyeCenter - 300) << " " << 100 * abs(eyeCenter - 300) / 20 + 200; + + if (eyeCenter < 250 || eyeCenter > 350) + { +// ProMemory::getInstance().moto->autoPosition(eyeCenter); + emit motoControl(eyeCenter); + +// this->msleep(100 * abs(eyeCenter - 300) / 20 + 200); // 200ms后再判断 + } + } + */ + + // 分类器找脸 + cv::Rect faceRect = casic::face::CasicFaceInterface::getInstance().faceDetectByCVCascade(rawFrame, SettingConfig::getInstance().MIN_WORK_FACE_SIZE); + QString facePos = QString("%1 * %2, (%3, %4), (%5, %6)").arg(faceRect.width).arg(faceRect.height) + .arg(faceRect.x).arg(faceRect.y).arg(faceRect.x + faceRect.width).arg(faceRect.y + faceRect.height); + + if (faceRect.width != 0) + { + // 通过人脸的大小判断距离,提示靠近或者远离 + if (faceRect.width < 360) + { + emit updateTips(QString("距离太远,请靠近 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#9F1919"); + } else if (faceRect.width >= 360 && faceRect.width <= 480) + { + emit updateTips(QString("正在识别,请保持 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#248A53"); + + // 位置合适 开始识别 +// ProMemory::getInstance().irisRecogPro->setWorking(true); +// ProMemory::getInstance().irisCam->startCapture(); +// this->setWorking(false); + } else if (faceRect.width > 480) + { + emit updateTips(QString("距离太近,请远离 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#9F1919"); + } + } + + this->msleep(500); + } +} + + +void CameraPositionController::checkFacePosition() +{ + +} diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp index f202cfe..bc8018b 100644 --- a/CasicBioRecWin.cpp +++ b/CasicBioRecWin.cpp @@ -6,7 +6,7 @@ , ui(new Ui::CasicBioRecWin) { // 打开外部可执行程序 - outExe = new QProcess(this); +// outExe = new QProcess(this); // outExe->start(SettingConfig::getInstance().OUT_EXE_FILE); ui->setupUi(this); @@ -31,6 +31,7 @@ initFaceRecogThread(); // 人脸识别线程 initIrisRegistThread(); // 虹膜注册线程 initIrisRecogThread(); // 虹膜识别线程 + initCameraPositionThread(); // 调整相机位置 // 初始化人脸相机控制 ProMemory::getInstance().faceCam = new FaceCameraController(this); @@ -49,6 +50,12 @@ connect(ProMemory::getInstance().irisCam->rightHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, addPersonForm, &AddPersonForm::drawIrisImageOnFrame); + // 初始化电机控制 + ProMemory::getInstance().moto = new MotoController(this); + ProMemory::getInstance().moto->initSerialMCU(); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::motoControl, + ProMemory::getInstance().moto, &MotoController::autoPosition); + // 打印日志 LOG(INFO) << QString("应用程序启动成功[Application Startup Success]").toStdString(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::MAIN_PAGE; @@ -72,6 +79,10 @@ ProMemory::getInstance().irisRecogPro->deleteLater(); ProMemory::getInstance().irisRecogPro->wait(); + ProMemory::getInstance().camPosCtrl->exitThread(); + ProMemory::getInstance().camPosCtrl->deleteLater(); + ProMemory::getInstance().camPosCtrl->wait(); + // 关闭自动启动的外部程序 // outExe->close(); // delete outExe; @@ -81,12 +92,14 @@ delete ProMemory::getInstance().faceRecogPro; delete ProMemory::getInstance().irisRegistPro; delete ProMemory::getInstance().irisRecogPro; + delete ProMemory::getInstance().camPosCtrl; } void CasicBioRecWin::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: + LOG(INFO) << "" << std::endl; QTimer::singleShot(100, qApp, SLOT(quit())); default: @@ -204,8 +217,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -244,8 +255,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -255,3 +264,17 @@ ProMemory::getInstance().irisRecogPro->start(); } + +void CasicBioRecWin::initCameraPositionThread() +{ + // 调整相机位置处理 + ProMemory::getInstance().camPosCtrl = new CameraPositionController(this); + + // 绑定信号与槽函数 + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTips, + recogResultForm, &RecognizeResultForm::updateRecogTips); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTipsBackgroundColor, + recogResultForm, &RecognizeResultForm::updateRecogTipsColor); + + ProMemory::getInstance().camPosCtrl->start(); +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h index b70245a..b5a3db9 100644 --- a/CasicBioRecWin.h +++ b/CasicBioRecWin.h @@ -54,6 +54,7 @@ void initFaceRecogThread(); void initIrisRegistThread(); void initIrisRecogThread(); + void initCameraPositionThread(); }; #endif // CASICBIORECWIN_H diff --git a/RecognizeResultForm.cpp b/RecognizeResultForm.cpp index e45a191..b340be9 100644 --- a/RecognizeResultForm.cpp +++ b/RecognizeResultForm.cpp @@ -20,7 +20,7 @@ RecognizeResultForm::~RecognizeResultForm() { - delete ui; + delete ui; } void RecognizeResultForm::startWorkingRecognize() @@ -29,23 +29,32 @@ switch (SettingConfig::getInstance().RECOG_TYPE) { case 1: // 人脸识别 + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); break; case 2: // 虹膜识别 + ProMemory::getInstance().clearIrisQueue(); +// ProMemory::getInstance().camPosCtrl->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; case 3: + // 双认证 先打开人脸识别 成功后再进行虹膜识别 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(true); + break; case 4: // 人脸和虹膜都需要打开 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; } - // 将界面切换到识别界面 RecognizeResultForm + // 开始拍图并显示视频 ProMemory::getInstance().faceCam->openFaceCamera(SettingConfig::getInstance().FACE_FRAME_INTERVAL); ui->labBackground->raise(); @@ -80,6 +89,14 @@ ui->widgetFail->raise(); ui->widgetFail->show(); + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().camPosCtrl->setWorking(false); + + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(false); + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ ui->labBackground->raise(); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -137,9 +154,9 @@ case 1: { // 仅人脸识别 - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); LOG(DEBUG) << QString("[RecognizeResultForm] 人脸识别成功 [%1]").arg(CasicFaceRecState::getInstance().toString()).toStdString(); @@ -158,9 +175,12 @@ case 2: { // 仅虹膜识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + // 停止控制电机和提示 + ProMemory::getInstance().camPosCtrl->setWorking(false); LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜识别成功 [%1]").arg(CasicIrisRecState::getInstance().toString()).toStdString(); @@ -179,13 +199,13 @@ case 4: { // 任意识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); QString logStr = QString("[RecognizeResultForm]%1识别成功[%2]"); if (faceOrIris == 1) @@ -213,42 +233,56 @@ if (faceOrIris == 1) { this->personIdByFace = personId; + + // 人脸识别成功后 开始进行虹膜识别 + // 1. 首先停止人脸识别 + ProMemory::getInstance().faceRecogPro->setWorking(false); + ProMemory::getInstance().clearFaceQueue(); + + // 2. 虹膜识别开始 + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().camPosCtrl->setWorking(true); } else if (faceOrIris == 2) { this->personIdByIris = personId; + + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) + { + // 只有一个成功的结果 需要等待下次 + return; + } else if (personIdByFace != personIdByIris) + { + // 人脸和虹膜识别的不是同一人 识别失败 + LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); + SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); + showRecogFailure(); + } else + { + LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); + showRecognizeResult(personId); + + // 识别记录存入数据库 + RecognitionRecordDao recDao; + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("type", "3"); + record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); + recDao.save(record); + } } - - if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) - { - // 只有一个成功的结果 需要等待下次 - return; - } else if (personIdByFace != personIdByIris) - { - // 人脸和虹膜识别的不是同一人 识别失败 - LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); - SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); - showRecogFailure(); - } else - { - LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); - showRecognizeResult(personId); - } - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - ProMemory::getInstance().clearFaceQueue(); - ProMemory::getInstance().faceRecogPro->setWorking(false); - ProMemory::getInstance().faceCam->stopTakingPhoto(); - - // 识别记录存入数据库 - RecognitionRecordDao recDao; - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("type", "4"); - record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); - recDao.save(record); } } + +void RecognizeResultForm::updateRecogTips(QString tipsText) +{ + ui->labTitle->setText(tipsText); +} +void RecognizeResultForm::updateRecogTipsColor(QString bgColor) +{ + ui->labTitle->setStyleSheet("background: " + bgColor); +} diff --git a/RecognizeResultForm.h b/RecognizeResultForm.h index 2c51865..65dd8ad 100644 --- a/RecognizeResultForm.h +++ b/RecognizeResultForm.h @@ -30,6 +30,8 @@ void startWorkingRecognize(); // 开始工作 void drawImageOnHomeForm(QImage imageDisp); + void updateRecogTips(QString tipsText); + void updateRecogTipsColor(QString bgColor); private: Ui::RecognizeResultForm *ui; diff --git a/StartupForm.cpp b/StartupForm.cpp index 16c4dfc..cf20de1 100644 --- a/StartupForm.cpp +++ b/StartupForm.cpp @@ -20,17 +20,23 @@ } // 设置弹簧的高度和宽度 - ui->vsTop->changeSize(0, 200); - ui->vsMidd->changeSize(0, 100); ui->hsLeft->changeSize(400, 0); ui->hsMidd->changeSize(150, 0); + // 绑定时间和日期的标签单击事件 单击即开始识别 + connect(ui->labDate, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + connect(ui->labTime, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + // 初始化更新界面的定时器 // 每秒执行一次 connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &StartupForm::updateDateAndTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, - this, &StartupForm::takeOneFrameForCheckStatus); +// connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, +// this, &StartupForm::takeOneFrameForCheckStatus); TimeCounterUtil::getInstance().clockCounter->start(1000); } diff --git a/StartupForm.h b/StartupForm.h index f2850e9..fc79be0 100644 --- a/StartupForm.h +++ b/StartupForm.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "casic/ProMemory.h" #include "utils/UtilInclude.h" diff --git a/StartupForm.ui b/StartupForm.ui index afb610f..de353f3 100644 --- a/StartupForm.ui +++ b/StartupForm.ui @@ -15,20 +15,7 @@ - - - Qt::Vertical - - - - 17 - 166 - - - - - - + TextLabel @@ -38,7 +25,7 @@ - + TextLabel @@ -48,19 +35,6 @@ - - - Qt::Vertical - - - - 17 - 167 - - - - - @@ -158,6 +132,13 @@ + + + QDblClickLabel + QLabel +
QDblClickLabel.h
+
+
diff --git a/casic/ProMemory.h b/casic/ProMemory.h index 3e9fbd4..02a14cf 100644 --- a/casic/ProMemory.h +++ b/casic/ProMemory.h @@ -16,6 +16,8 @@ #include "device/face/FaceRecogProcess.h" #include "device/iris/IrisRegistProcess.h" #include "device/iris/IrisRecogProcess.h" +#include "device/MotoController.h" +#include "device/CameraPositionController.h" class FaceCameraController; class IrisCameraController; @@ -23,6 +25,8 @@ class FaceRecogProcess; class IrisRegistProcess; class IrisRecogProcess; +class MotoController; +class CameraPositionController; class ProMemory { @@ -66,6 +70,10 @@ IrisRegistProcess * irisRegistPro; IrisRecogProcess * irisRecogPro; + MotoController * moto; + + CameraPositionController * camPosCtrl; + private: ProMemory(); diff --git a/casic/face/CasicFaceInterface.cpp b/casic/face/CasicFaceInterface.cpp index f530212..3cb2118 100644 --- a/casic/face/CasicFaceInterface.cpp +++ b/casic/face/CasicFaceInterface.cpp @@ -45,8 +45,6 @@ delete this->cascade; this->cascade = nullptr; } - - LOG(DEBUG) << "delete models in destructor"; } void casic::face::CasicFaceInterface::setDetectorModelPath(std::string detectorModelPath) @@ -384,6 +382,9 @@ cv::Size minRectSize(minFaceSize, minFaceSize); cv::Size maxRectSize(maxFaceSize, maxFaceSize); + QElapsedTimer timer; + timer.start(); + // ★分类器对象调用 cascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); @@ -391,6 +392,8 @@ { return cv::Rect(0, 0, 0, 0); } + + LOG(DEBUG) << QString("人脸分类检测算法[tm: %1 ms][%2, %3]").arg(timer.elapsed()).arg(rect.at(0).width).arg(rect.at(0).height).toStdString(); return rect.at(0); } @@ -424,7 +427,7 @@ return rect.at(0); } -bool casic::face::CasicFaceInterface::hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize) +std::vector casic::face::CasicFaceInterface::eyeDetectByCVCascade(cv::Mat frame, int minEyeSize) { // 构建openCV自带的眼睛分类器 if (this->eyeCascade == nullptr) @@ -433,14 +436,14 @@ this->eyeCascade->load(cvEyeCascadeName); } - std::vector rect; + std::vector rectVec; cv::Size minRectSize(minEyeSize, minEyeSize); cv::Size maxRectSize(maxEyeSize, maxEyeSize); // ★分类器对象调用 - eyeCascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); + eyeCascade->detectMultiScale(frame, rectVec, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); - return rect.size() == 0 ? false : true; + return rectVec; } void casic::face::CasicFaceInterface::setMinFaceSize(int minFaceSize) diff --git a/casic/face/CasicFaceInterface.h b/casic/face/CasicFaceInterface.h index 9d8b8ea..1753bd1 100644 --- a/casic/face/CasicFaceInterface.h +++ b/casic/face/CasicFaceInterface.h @@ -52,7 +52,7 @@ cv::Rect faceDetectByCVCascade(cv::Mat frame, int minFaceSize); cv::Rect eyeDetectByCVCascade(cv::Mat frame); - bool hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize); + std::vector eyeDetectByCVCascade(cv::Mat frame, int minEyeSize); void setMinFaceSize(int minFaceSize); void setMinEyeSize(int minEyeSize); private: diff --git a/dao/RecognitionRecordDao.cpp b/dao/RecognitionRecordDao.cpp index 403894a..d7103f9 100644 --- a/dao/RecognitionRecordDao.cpp +++ b/dao/RecognitionRecordDao.cpp @@ -91,13 +91,14 @@ .arg(object.value("type").toString()) .arg(object.value("dev_code").toString()) .arg(object.value("door_code").toString()) - .arg(object.value("inout_type").toString()); + .arg(object.value("inout_type").toString()) + .arg(object.value("debug_info").toString()); query.prepare(sql); LOG(DEBUG) << sql.toStdString(); // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES ('%1', '%2')") + QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES ('%1', '%2')") .arg(id).arg(object.value("debug_info").toString()); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/device/CameraPositionController.cpp b/device/CameraPositionController.cpp new file mode 100644 index 0000000..577c9ad --- /dev/null +++ b/device/CameraPositionController.cpp @@ -0,0 +1,91 @@ +#include "CameraPositionController.h" + +CameraPositionController::CameraPositionController(QObject *parent) : QThread(parent) +{ + this->working = false; + this->exit = false; +} + +CameraPositionController::~CameraPositionController() +{ + this->setWorking(false); +} + +void CameraPositionController::setWorking(bool working) +{ + this->working = working; +} +void CameraPositionController::exitThread() +{ + this->working = false; + this->exit = true; +} + +void CameraPositionController::run() +{ + while (exit == false) + { + if (this->working == false) + { + this->msleep(200); // 200ms后再判断 + continue; + } + + // 取一幅图像 + cv::Mat rawFrame = ProMemory::getInstance().faceCam->takeOneRawFrame(); +/* + // 分类器找眼睛 + cv::Rect eyeRect = casic::face::CasicFaceInterface::getInstance().eyeDetectByCVCascade(rawFrame); + if (eyeRect.width != 0) + { + // 眼睛的位置 + int eyeCenter = eyeRect.y + eyeRect.height / 2; + LOG(DEBUG) << eyeCenter << " " << abs(eyeCenter - 300) << " " << 100 * abs(eyeCenter - 300) / 20 + 200; + + if (eyeCenter < 250 || eyeCenter > 350) + { +// ProMemory::getInstance().moto->autoPosition(eyeCenter); + emit motoControl(eyeCenter); + +// this->msleep(100 * abs(eyeCenter - 300) / 20 + 200); // 200ms后再判断 + } + } + */ + + // 分类器找脸 + cv::Rect faceRect = casic::face::CasicFaceInterface::getInstance().faceDetectByCVCascade(rawFrame, SettingConfig::getInstance().MIN_WORK_FACE_SIZE); + QString facePos = QString("%1 * %2, (%3, %4), (%5, %6)").arg(faceRect.width).arg(faceRect.height) + .arg(faceRect.x).arg(faceRect.y).arg(faceRect.x + faceRect.width).arg(faceRect.y + faceRect.height); + + if (faceRect.width != 0) + { + // 通过人脸的大小判断距离,提示靠近或者远离 + if (faceRect.width < 360) + { + emit updateTips(QString("距离太远,请靠近 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#9F1919"); + } else if (faceRect.width >= 360 && faceRect.width <= 480) + { + emit updateTips(QString("正在识别,请保持 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#248A53"); + + // 位置合适 开始识别 +// ProMemory::getInstance().irisRecogPro->setWorking(true); +// ProMemory::getInstance().irisCam->startCapture(); +// this->setWorking(false); + } else if (faceRect.width > 480) + { + emit updateTips(QString("距离太近,请远离 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#9F1919"); + } + } + + this->msleep(500); + } +} + + +void CameraPositionController::checkFacePosition() +{ + +} diff --git a/device/CameraPositionController.h b/device/CameraPositionController.h new file mode 100644 index 0000000..9520b14 --- /dev/null +++ b/device/CameraPositionController.h @@ -0,0 +1,39 @@ +#ifndef CAMERAPOSITIONCONTROLLER_H +#define CAMERAPOSITIONCONTROLLER_H + +#include +#include + +#include "opencv2/opencv.hpp" +#include "utils/UtilInclude.h" +#include "casic/ProMemory.h" + +class CameraPositionController : public QThread +{ + Q_OBJECT +public: + explicit CameraPositionController(QObject *parent = 0); + ~CameraPositionController(); + + void setWorking(bool working); + void exitThread(); + +protected: + //QThread的虚函数 + //线程处理函数 + //不能直接调用, 通过start()间接调用 + void run(); + + volatile bool working; + volatile bool exit; + +public slots: + void checkFacePosition(); + +signals: + void updateTips(QString tipsText); + void updateTipsBackgroundColor(QString bgColor); + void motoControl(int eyeCenter); +}; + +#endif // CAMERAPOSITIONCONTROLLER_H diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp index f202cfe..bc8018b 100644 --- a/CasicBioRecWin.cpp +++ b/CasicBioRecWin.cpp @@ -6,7 +6,7 @@ , ui(new Ui::CasicBioRecWin) { // 打开外部可执行程序 - outExe = new QProcess(this); +// outExe = new QProcess(this); // outExe->start(SettingConfig::getInstance().OUT_EXE_FILE); ui->setupUi(this); @@ -31,6 +31,7 @@ initFaceRecogThread(); // 人脸识别线程 initIrisRegistThread(); // 虹膜注册线程 initIrisRecogThread(); // 虹膜识别线程 + initCameraPositionThread(); // 调整相机位置 // 初始化人脸相机控制 ProMemory::getInstance().faceCam = new FaceCameraController(this); @@ -49,6 +50,12 @@ connect(ProMemory::getInstance().irisCam->rightHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, addPersonForm, &AddPersonForm::drawIrisImageOnFrame); + // 初始化电机控制 + ProMemory::getInstance().moto = new MotoController(this); + ProMemory::getInstance().moto->initSerialMCU(); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::motoControl, + ProMemory::getInstance().moto, &MotoController::autoPosition); + // 打印日志 LOG(INFO) << QString("应用程序启动成功[Application Startup Success]").toStdString(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::MAIN_PAGE; @@ -72,6 +79,10 @@ ProMemory::getInstance().irisRecogPro->deleteLater(); ProMemory::getInstance().irisRecogPro->wait(); + ProMemory::getInstance().camPosCtrl->exitThread(); + ProMemory::getInstance().camPosCtrl->deleteLater(); + ProMemory::getInstance().camPosCtrl->wait(); + // 关闭自动启动的外部程序 // outExe->close(); // delete outExe; @@ -81,12 +92,14 @@ delete ProMemory::getInstance().faceRecogPro; delete ProMemory::getInstance().irisRegistPro; delete ProMemory::getInstance().irisRecogPro; + delete ProMemory::getInstance().camPosCtrl; } void CasicBioRecWin::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: + LOG(INFO) << "" << std::endl; QTimer::singleShot(100, qApp, SLOT(quit())); default: @@ -204,8 +217,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -244,8 +255,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -255,3 +264,17 @@ ProMemory::getInstance().irisRecogPro->start(); } + +void CasicBioRecWin::initCameraPositionThread() +{ + // 调整相机位置处理 + ProMemory::getInstance().camPosCtrl = new CameraPositionController(this); + + // 绑定信号与槽函数 + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTips, + recogResultForm, &RecognizeResultForm::updateRecogTips); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTipsBackgroundColor, + recogResultForm, &RecognizeResultForm::updateRecogTipsColor); + + ProMemory::getInstance().camPosCtrl->start(); +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h index b70245a..b5a3db9 100644 --- a/CasicBioRecWin.h +++ b/CasicBioRecWin.h @@ -54,6 +54,7 @@ void initFaceRecogThread(); void initIrisRegistThread(); void initIrisRecogThread(); + void initCameraPositionThread(); }; #endif // CASICBIORECWIN_H diff --git a/RecognizeResultForm.cpp b/RecognizeResultForm.cpp index e45a191..b340be9 100644 --- a/RecognizeResultForm.cpp +++ b/RecognizeResultForm.cpp @@ -20,7 +20,7 @@ RecognizeResultForm::~RecognizeResultForm() { - delete ui; + delete ui; } void RecognizeResultForm::startWorkingRecognize() @@ -29,23 +29,32 @@ switch (SettingConfig::getInstance().RECOG_TYPE) { case 1: // 人脸识别 + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); break; case 2: // 虹膜识别 + ProMemory::getInstance().clearIrisQueue(); +// ProMemory::getInstance().camPosCtrl->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; case 3: + // 双认证 先打开人脸识别 成功后再进行虹膜识别 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(true); + break; case 4: // 人脸和虹膜都需要打开 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; } - // 将界面切换到识别界面 RecognizeResultForm + // 开始拍图并显示视频 ProMemory::getInstance().faceCam->openFaceCamera(SettingConfig::getInstance().FACE_FRAME_INTERVAL); ui->labBackground->raise(); @@ -80,6 +89,14 @@ ui->widgetFail->raise(); ui->widgetFail->show(); + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().camPosCtrl->setWorking(false); + + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(false); + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ ui->labBackground->raise(); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -137,9 +154,9 @@ case 1: { // 仅人脸识别 - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); LOG(DEBUG) << QString("[RecognizeResultForm] 人脸识别成功 [%1]").arg(CasicFaceRecState::getInstance().toString()).toStdString(); @@ -158,9 +175,12 @@ case 2: { // 仅虹膜识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + // 停止控制电机和提示 + ProMemory::getInstance().camPosCtrl->setWorking(false); LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜识别成功 [%1]").arg(CasicIrisRecState::getInstance().toString()).toStdString(); @@ -179,13 +199,13 @@ case 4: { // 任意识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); QString logStr = QString("[RecognizeResultForm]%1识别成功[%2]"); if (faceOrIris == 1) @@ -213,42 +233,56 @@ if (faceOrIris == 1) { this->personIdByFace = personId; + + // 人脸识别成功后 开始进行虹膜识别 + // 1. 首先停止人脸识别 + ProMemory::getInstance().faceRecogPro->setWorking(false); + ProMemory::getInstance().clearFaceQueue(); + + // 2. 虹膜识别开始 + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().camPosCtrl->setWorking(true); } else if (faceOrIris == 2) { this->personIdByIris = personId; + + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) + { + // 只有一个成功的结果 需要等待下次 + return; + } else if (personIdByFace != personIdByIris) + { + // 人脸和虹膜识别的不是同一人 识别失败 + LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); + SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); + showRecogFailure(); + } else + { + LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); + showRecognizeResult(personId); + + // 识别记录存入数据库 + RecognitionRecordDao recDao; + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("type", "3"); + record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); + recDao.save(record); + } } - - if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) - { - // 只有一个成功的结果 需要等待下次 - return; - } else if (personIdByFace != personIdByIris) - { - // 人脸和虹膜识别的不是同一人 识别失败 - LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); - SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); - showRecogFailure(); - } else - { - LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); - showRecognizeResult(personId); - } - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - ProMemory::getInstance().clearFaceQueue(); - ProMemory::getInstance().faceRecogPro->setWorking(false); - ProMemory::getInstance().faceCam->stopTakingPhoto(); - - // 识别记录存入数据库 - RecognitionRecordDao recDao; - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("type", "4"); - record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); - recDao.save(record); } } + +void RecognizeResultForm::updateRecogTips(QString tipsText) +{ + ui->labTitle->setText(tipsText); +} +void RecognizeResultForm::updateRecogTipsColor(QString bgColor) +{ + ui->labTitle->setStyleSheet("background: " + bgColor); +} diff --git a/RecognizeResultForm.h b/RecognizeResultForm.h index 2c51865..65dd8ad 100644 --- a/RecognizeResultForm.h +++ b/RecognizeResultForm.h @@ -30,6 +30,8 @@ void startWorkingRecognize(); // 开始工作 void drawImageOnHomeForm(QImage imageDisp); + void updateRecogTips(QString tipsText); + void updateRecogTipsColor(QString bgColor); private: Ui::RecognizeResultForm *ui; diff --git a/StartupForm.cpp b/StartupForm.cpp index 16c4dfc..cf20de1 100644 --- a/StartupForm.cpp +++ b/StartupForm.cpp @@ -20,17 +20,23 @@ } // 设置弹簧的高度和宽度 - ui->vsTop->changeSize(0, 200); - ui->vsMidd->changeSize(0, 100); ui->hsLeft->changeSize(400, 0); ui->hsMidd->changeSize(150, 0); + // 绑定时间和日期的标签单击事件 单击即开始识别 + connect(ui->labDate, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + connect(ui->labTime, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + // 初始化更新界面的定时器 // 每秒执行一次 connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &StartupForm::updateDateAndTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, - this, &StartupForm::takeOneFrameForCheckStatus); +// connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, +// this, &StartupForm::takeOneFrameForCheckStatus); TimeCounterUtil::getInstance().clockCounter->start(1000); } diff --git a/StartupForm.h b/StartupForm.h index f2850e9..fc79be0 100644 --- a/StartupForm.h +++ b/StartupForm.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "casic/ProMemory.h" #include "utils/UtilInclude.h" diff --git a/StartupForm.ui b/StartupForm.ui index afb610f..de353f3 100644 --- a/StartupForm.ui +++ b/StartupForm.ui @@ -15,20 +15,7 @@ - - - Qt::Vertical - - - - 17 - 166 - - - - - - + TextLabel @@ -38,7 +25,7 @@ - + TextLabel @@ -48,19 +35,6 @@ - - - Qt::Vertical - - - - 17 - 167 - - - - - @@ -158,6 +132,13 @@ + + + QDblClickLabel + QLabel +
QDblClickLabel.h
+
+
diff --git a/casic/ProMemory.h b/casic/ProMemory.h index 3e9fbd4..02a14cf 100644 --- a/casic/ProMemory.h +++ b/casic/ProMemory.h @@ -16,6 +16,8 @@ #include "device/face/FaceRecogProcess.h" #include "device/iris/IrisRegistProcess.h" #include "device/iris/IrisRecogProcess.h" +#include "device/MotoController.h" +#include "device/CameraPositionController.h" class FaceCameraController; class IrisCameraController; @@ -23,6 +25,8 @@ class FaceRecogProcess; class IrisRegistProcess; class IrisRecogProcess; +class MotoController; +class CameraPositionController; class ProMemory { @@ -66,6 +70,10 @@ IrisRegistProcess * irisRegistPro; IrisRecogProcess * irisRecogPro; + MotoController * moto; + + CameraPositionController * camPosCtrl; + private: ProMemory(); diff --git a/casic/face/CasicFaceInterface.cpp b/casic/face/CasicFaceInterface.cpp index f530212..3cb2118 100644 --- a/casic/face/CasicFaceInterface.cpp +++ b/casic/face/CasicFaceInterface.cpp @@ -45,8 +45,6 @@ delete this->cascade; this->cascade = nullptr; } - - LOG(DEBUG) << "delete models in destructor"; } void casic::face::CasicFaceInterface::setDetectorModelPath(std::string detectorModelPath) @@ -384,6 +382,9 @@ cv::Size minRectSize(minFaceSize, minFaceSize); cv::Size maxRectSize(maxFaceSize, maxFaceSize); + QElapsedTimer timer; + timer.start(); + // ★分类器对象调用 cascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); @@ -391,6 +392,8 @@ { return cv::Rect(0, 0, 0, 0); } + + LOG(DEBUG) << QString("人脸分类检测算法[tm: %1 ms][%2, %3]").arg(timer.elapsed()).arg(rect.at(0).width).arg(rect.at(0).height).toStdString(); return rect.at(0); } @@ -424,7 +427,7 @@ return rect.at(0); } -bool casic::face::CasicFaceInterface::hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize) +std::vector casic::face::CasicFaceInterface::eyeDetectByCVCascade(cv::Mat frame, int minEyeSize) { // 构建openCV自带的眼睛分类器 if (this->eyeCascade == nullptr) @@ -433,14 +436,14 @@ this->eyeCascade->load(cvEyeCascadeName); } - std::vector rect; + std::vector rectVec; cv::Size minRectSize(minEyeSize, minEyeSize); cv::Size maxRectSize(maxEyeSize, maxEyeSize); // ★分类器对象调用 - eyeCascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); + eyeCascade->detectMultiScale(frame, rectVec, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); - return rect.size() == 0 ? false : true; + return rectVec; } void casic::face::CasicFaceInterface::setMinFaceSize(int minFaceSize) diff --git a/casic/face/CasicFaceInterface.h b/casic/face/CasicFaceInterface.h index 9d8b8ea..1753bd1 100644 --- a/casic/face/CasicFaceInterface.h +++ b/casic/face/CasicFaceInterface.h @@ -52,7 +52,7 @@ cv::Rect faceDetectByCVCascade(cv::Mat frame, int minFaceSize); cv::Rect eyeDetectByCVCascade(cv::Mat frame); - bool hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize); + std::vector eyeDetectByCVCascade(cv::Mat frame, int minEyeSize); void setMinFaceSize(int minFaceSize); void setMinEyeSize(int minEyeSize); private: diff --git a/dao/RecognitionRecordDao.cpp b/dao/RecognitionRecordDao.cpp index 403894a..d7103f9 100644 --- a/dao/RecognitionRecordDao.cpp +++ b/dao/RecognitionRecordDao.cpp @@ -91,13 +91,14 @@ .arg(object.value("type").toString()) .arg(object.value("dev_code").toString()) .arg(object.value("door_code").toString()) - .arg(object.value("inout_type").toString()); + .arg(object.value("inout_type").toString()) + .arg(object.value("debug_info").toString()); query.prepare(sql); LOG(DEBUG) << sql.toStdString(); // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES ('%1', '%2')") + QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES ('%1', '%2')") .arg(id).arg(object.value("debug_info").toString()); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/device/CameraPositionController.cpp b/device/CameraPositionController.cpp new file mode 100644 index 0000000..577c9ad --- /dev/null +++ b/device/CameraPositionController.cpp @@ -0,0 +1,91 @@ +#include "CameraPositionController.h" + +CameraPositionController::CameraPositionController(QObject *parent) : QThread(parent) +{ + this->working = false; + this->exit = false; +} + +CameraPositionController::~CameraPositionController() +{ + this->setWorking(false); +} + +void CameraPositionController::setWorking(bool working) +{ + this->working = working; +} +void CameraPositionController::exitThread() +{ + this->working = false; + this->exit = true; +} + +void CameraPositionController::run() +{ + while (exit == false) + { + if (this->working == false) + { + this->msleep(200); // 200ms后再判断 + continue; + } + + // 取一幅图像 + cv::Mat rawFrame = ProMemory::getInstance().faceCam->takeOneRawFrame(); +/* + // 分类器找眼睛 + cv::Rect eyeRect = casic::face::CasicFaceInterface::getInstance().eyeDetectByCVCascade(rawFrame); + if (eyeRect.width != 0) + { + // 眼睛的位置 + int eyeCenter = eyeRect.y + eyeRect.height / 2; + LOG(DEBUG) << eyeCenter << " " << abs(eyeCenter - 300) << " " << 100 * abs(eyeCenter - 300) / 20 + 200; + + if (eyeCenter < 250 || eyeCenter > 350) + { +// ProMemory::getInstance().moto->autoPosition(eyeCenter); + emit motoControl(eyeCenter); + +// this->msleep(100 * abs(eyeCenter - 300) / 20 + 200); // 200ms后再判断 + } + } + */ + + // 分类器找脸 + cv::Rect faceRect = casic::face::CasicFaceInterface::getInstance().faceDetectByCVCascade(rawFrame, SettingConfig::getInstance().MIN_WORK_FACE_SIZE); + QString facePos = QString("%1 * %2, (%3, %4), (%5, %6)").arg(faceRect.width).arg(faceRect.height) + .arg(faceRect.x).arg(faceRect.y).arg(faceRect.x + faceRect.width).arg(faceRect.y + faceRect.height); + + if (faceRect.width != 0) + { + // 通过人脸的大小判断距离,提示靠近或者远离 + if (faceRect.width < 360) + { + emit updateTips(QString("距离太远,请靠近 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#9F1919"); + } else if (faceRect.width >= 360 && faceRect.width <= 480) + { + emit updateTips(QString("正在识别,请保持 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#248A53"); + + // 位置合适 开始识别 +// ProMemory::getInstance().irisRecogPro->setWorking(true); +// ProMemory::getInstance().irisCam->startCapture(); +// this->setWorking(false); + } else if (faceRect.width > 480) + { + emit updateTips(QString("距离太近,请远离 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#9F1919"); + } + } + + this->msleep(500); + } +} + + +void CameraPositionController::checkFacePosition() +{ + +} diff --git a/device/CameraPositionController.h b/device/CameraPositionController.h new file mode 100644 index 0000000..9520b14 --- /dev/null +++ b/device/CameraPositionController.h @@ -0,0 +1,39 @@ +#ifndef CAMERAPOSITIONCONTROLLER_H +#define CAMERAPOSITIONCONTROLLER_H + +#include +#include + +#include "opencv2/opencv.hpp" +#include "utils/UtilInclude.h" +#include "casic/ProMemory.h" + +class CameraPositionController : public QThread +{ + Q_OBJECT +public: + explicit CameraPositionController(QObject *parent = 0); + ~CameraPositionController(); + + void setWorking(bool working); + void exitThread(); + +protected: + //QThread的虚函数 + //线程处理函数 + //不能直接调用, 通过start()间接调用 + void run(); + + volatile bool working; + volatile bool exit; + +public slots: + void checkFacePosition(); + +signals: + void updateTips(QString tipsText); + void updateTipsBackgroundColor(QString bgColor); + void motoControl(int eyeCenter); +}; + +#endif // CAMERAPOSITIONCONTROLLER_H diff --git a/device/FaceCameraController.cpp b/device/FaceCameraController.cpp index 0fe4b4c..2a4d7cb 100644 --- a/device/FaceCameraController.cpp +++ b/device/FaceCameraController.cpp @@ -41,8 +41,7 @@ void FaceCameraController::closeFaceCamera() { faceCap->release(); - - delete faceCap; +// delete faceCap; } @@ -88,7 +87,7 @@ // 拍图 faceCap->read(faceMat); - LOG(TRACE) << "TAKE ONE FACE FRAME " << faceMat.cols << " * " << faceMat.rows; + LOG(TRACE) << QThread::currentThreadId() << " TAKE ONE FACE FRAME " << faceMat.cols << " * " << faceMat.rows; // 左右翻转 cv::Mat imageMatMiir; diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp index f202cfe..bc8018b 100644 --- a/CasicBioRecWin.cpp +++ b/CasicBioRecWin.cpp @@ -6,7 +6,7 @@ , ui(new Ui::CasicBioRecWin) { // 打开外部可执行程序 - outExe = new QProcess(this); +// outExe = new QProcess(this); // outExe->start(SettingConfig::getInstance().OUT_EXE_FILE); ui->setupUi(this); @@ -31,6 +31,7 @@ initFaceRecogThread(); // 人脸识别线程 initIrisRegistThread(); // 虹膜注册线程 initIrisRecogThread(); // 虹膜识别线程 + initCameraPositionThread(); // 调整相机位置 // 初始化人脸相机控制 ProMemory::getInstance().faceCam = new FaceCameraController(this); @@ -49,6 +50,12 @@ connect(ProMemory::getInstance().irisCam->rightHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, addPersonForm, &AddPersonForm::drawIrisImageOnFrame); + // 初始化电机控制 + ProMemory::getInstance().moto = new MotoController(this); + ProMemory::getInstance().moto->initSerialMCU(); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::motoControl, + ProMemory::getInstance().moto, &MotoController::autoPosition); + // 打印日志 LOG(INFO) << QString("应用程序启动成功[Application Startup Success]").toStdString(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::MAIN_PAGE; @@ -72,6 +79,10 @@ ProMemory::getInstance().irisRecogPro->deleteLater(); ProMemory::getInstance().irisRecogPro->wait(); + ProMemory::getInstance().camPosCtrl->exitThread(); + ProMemory::getInstance().camPosCtrl->deleteLater(); + ProMemory::getInstance().camPosCtrl->wait(); + // 关闭自动启动的外部程序 // outExe->close(); // delete outExe; @@ -81,12 +92,14 @@ delete ProMemory::getInstance().faceRecogPro; delete ProMemory::getInstance().irisRegistPro; delete ProMemory::getInstance().irisRecogPro; + delete ProMemory::getInstance().camPosCtrl; } void CasicBioRecWin::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: + LOG(INFO) << "" << std::endl; QTimer::singleShot(100, qApp, SLOT(quit())); default: @@ -204,8 +217,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -244,8 +255,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -255,3 +264,17 @@ ProMemory::getInstance().irisRecogPro->start(); } + +void CasicBioRecWin::initCameraPositionThread() +{ + // 调整相机位置处理 + ProMemory::getInstance().camPosCtrl = new CameraPositionController(this); + + // 绑定信号与槽函数 + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTips, + recogResultForm, &RecognizeResultForm::updateRecogTips); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTipsBackgroundColor, + recogResultForm, &RecognizeResultForm::updateRecogTipsColor); + + ProMemory::getInstance().camPosCtrl->start(); +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h index b70245a..b5a3db9 100644 --- a/CasicBioRecWin.h +++ b/CasicBioRecWin.h @@ -54,6 +54,7 @@ void initFaceRecogThread(); void initIrisRegistThread(); void initIrisRecogThread(); + void initCameraPositionThread(); }; #endif // CASICBIORECWIN_H diff --git a/RecognizeResultForm.cpp b/RecognizeResultForm.cpp index e45a191..b340be9 100644 --- a/RecognizeResultForm.cpp +++ b/RecognizeResultForm.cpp @@ -20,7 +20,7 @@ RecognizeResultForm::~RecognizeResultForm() { - delete ui; + delete ui; } void RecognizeResultForm::startWorkingRecognize() @@ -29,23 +29,32 @@ switch (SettingConfig::getInstance().RECOG_TYPE) { case 1: // 人脸识别 + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); break; case 2: // 虹膜识别 + ProMemory::getInstance().clearIrisQueue(); +// ProMemory::getInstance().camPosCtrl->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; case 3: + // 双认证 先打开人脸识别 成功后再进行虹膜识别 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(true); + break; case 4: // 人脸和虹膜都需要打开 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; } - // 将界面切换到识别界面 RecognizeResultForm + // 开始拍图并显示视频 ProMemory::getInstance().faceCam->openFaceCamera(SettingConfig::getInstance().FACE_FRAME_INTERVAL); ui->labBackground->raise(); @@ -80,6 +89,14 @@ ui->widgetFail->raise(); ui->widgetFail->show(); + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().camPosCtrl->setWorking(false); + + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(false); + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ ui->labBackground->raise(); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -137,9 +154,9 @@ case 1: { // 仅人脸识别 - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); LOG(DEBUG) << QString("[RecognizeResultForm] 人脸识别成功 [%1]").arg(CasicFaceRecState::getInstance().toString()).toStdString(); @@ -158,9 +175,12 @@ case 2: { // 仅虹膜识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + // 停止控制电机和提示 + ProMemory::getInstance().camPosCtrl->setWorking(false); LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜识别成功 [%1]").arg(CasicIrisRecState::getInstance().toString()).toStdString(); @@ -179,13 +199,13 @@ case 4: { // 任意识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); QString logStr = QString("[RecognizeResultForm]%1识别成功[%2]"); if (faceOrIris == 1) @@ -213,42 +233,56 @@ if (faceOrIris == 1) { this->personIdByFace = personId; + + // 人脸识别成功后 开始进行虹膜识别 + // 1. 首先停止人脸识别 + ProMemory::getInstance().faceRecogPro->setWorking(false); + ProMemory::getInstance().clearFaceQueue(); + + // 2. 虹膜识别开始 + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().camPosCtrl->setWorking(true); } else if (faceOrIris == 2) { this->personIdByIris = personId; + + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) + { + // 只有一个成功的结果 需要等待下次 + return; + } else if (personIdByFace != personIdByIris) + { + // 人脸和虹膜识别的不是同一人 识别失败 + LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); + SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); + showRecogFailure(); + } else + { + LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); + showRecognizeResult(personId); + + // 识别记录存入数据库 + RecognitionRecordDao recDao; + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("type", "3"); + record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); + recDao.save(record); + } } - - if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) - { - // 只有一个成功的结果 需要等待下次 - return; - } else if (personIdByFace != personIdByIris) - { - // 人脸和虹膜识别的不是同一人 识别失败 - LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); - SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); - showRecogFailure(); - } else - { - LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); - showRecognizeResult(personId); - } - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - ProMemory::getInstance().clearFaceQueue(); - ProMemory::getInstance().faceRecogPro->setWorking(false); - ProMemory::getInstance().faceCam->stopTakingPhoto(); - - // 识别记录存入数据库 - RecognitionRecordDao recDao; - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("type", "4"); - record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); - recDao.save(record); } } + +void RecognizeResultForm::updateRecogTips(QString tipsText) +{ + ui->labTitle->setText(tipsText); +} +void RecognizeResultForm::updateRecogTipsColor(QString bgColor) +{ + ui->labTitle->setStyleSheet("background: " + bgColor); +} diff --git a/RecognizeResultForm.h b/RecognizeResultForm.h index 2c51865..65dd8ad 100644 --- a/RecognizeResultForm.h +++ b/RecognizeResultForm.h @@ -30,6 +30,8 @@ void startWorkingRecognize(); // 开始工作 void drawImageOnHomeForm(QImage imageDisp); + void updateRecogTips(QString tipsText); + void updateRecogTipsColor(QString bgColor); private: Ui::RecognizeResultForm *ui; diff --git a/StartupForm.cpp b/StartupForm.cpp index 16c4dfc..cf20de1 100644 --- a/StartupForm.cpp +++ b/StartupForm.cpp @@ -20,17 +20,23 @@ } // 设置弹簧的高度和宽度 - ui->vsTop->changeSize(0, 200); - ui->vsMidd->changeSize(0, 100); ui->hsLeft->changeSize(400, 0); ui->hsMidd->changeSize(150, 0); + // 绑定时间和日期的标签单击事件 单击即开始识别 + connect(ui->labDate, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + connect(ui->labTime, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + // 初始化更新界面的定时器 // 每秒执行一次 connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &StartupForm::updateDateAndTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, - this, &StartupForm::takeOneFrameForCheckStatus); +// connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, +// this, &StartupForm::takeOneFrameForCheckStatus); TimeCounterUtil::getInstance().clockCounter->start(1000); } diff --git a/StartupForm.h b/StartupForm.h index f2850e9..fc79be0 100644 --- a/StartupForm.h +++ b/StartupForm.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "casic/ProMemory.h" #include "utils/UtilInclude.h" diff --git a/StartupForm.ui b/StartupForm.ui index afb610f..de353f3 100644 --- a/StartupForm.ui +++ b/StartupForm.ui @@ -15,20 +15,7 @@ - - - Qt::Vertical - - - - 17 - 166 - - - - - - + TextLabel @@ -38,7 +25,7 @@ - + TextLabel @@ -48,19 +35,6 @@ - - - Qt::Vertical - - - - 17 - 167 - - - - - @@ -158,6 +132,13 @@ + + + QDblClickLabel + QLabel +
QDblClickLabel.h
+
+
diff --git a/casic/ProMemory.h b/casic/ProMemory.h index 3e9fbd4..02a14cf 100644 --- a/casic/ProMemory.h +++ b/casic/ProMemory.h @@ -16,6 +16,8 @@ #include "device/face/FaceRecogProcess.h" #include "device/iris/IrisRegistProcess.h" #include "device/iris/IrisRecogProcess.h" +#include "device/MotoController.h" +#include "device/CameraPositionController.h" class FaceCameraController; class IrisCameraController; @@ -23,6 +25,8 @@ class FaceRecogProcess; class IrisRegistProcess; class IrisRecogProcess; +class MotoController; +class CameraPositionController; class ProMemory { @@ -66,6 +70,10 @@ IrisRegistProcess * irisRegistPro; IrisRecogProcess * irisRecogPro; + MotoController * moto; + + CameraPositionController * camPosCtrl; + private: ProMemory(); diff --git a/casic/face/CasicFaceInterface.cpp b/casic/face/CasicFaceInterface.cpp index f530212..3cb2118 100644 --- a/casic/face/CasicFaceInterface.cpp +++ b/casic/face/CasicFaceInterface.cpp @@ -45,8 +45,6 @@ delete this->cascade; this->cascade = nullptr; } - - LOG(DEBUG) << "delete models in destructor"; } void casic::face::CasicFaceInterface::setDetectorModelPath(std::string detectorModelPath) @@ -384,6 +382,9 @@ cv::Size minRectSize(minFaceSize, minFaceSize); cv::Size maxRectSize(maxFaceSize, maxFaceSize); + QElapsedTimer timer; + timer.start(); + // ★分类器对象调用 cascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); @@ -391,6 +392,8 @@ { return cv::Rect(0, 0, 0, 0); } + + LOG(DEBUG) << QString("人脸分类检测算法[tm: %1 ms][%2, %3]").arg(timer.elapsed()).arg(rect.at(0).width).arg(rect.at(0).height).toStdString(); return rect.at(0); } @@ -424,7 +427,7 @@ return rect.at(0); } -bool casic::face::CasicFaceInterface::hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize) +std::vector casic::face::CasicFaceInterface::eyeDetectByCVCascade(cv::Mat frame, int minEyeSize) { // 构建openCV自带的眼睛分类器 if (this->eyeCascade == nullptr) @@ -433,14 +436,14 @@ this->eyeCascade->load(cvEyeCascadeName); } - std::vector rect; + std::vector rectVec; cv::Size minRectSize(minEyeSize, minEyeSize); cv::Size maxRectSize(maxEyeSize, maxEyeSize); // ★分类器对象调用 - eyeCascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); + eyeCascade->detectMultiScale(frame, rectVec, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); - return rect.size() == 0 ? false : true; + return rectVec; } void casic::face::CasicFaceInterface::setMinFaceSize(int minFaceSize) diff --git a/casic/face/CasicFaceInterface.h b/casic/face/CasicFaceInterface.h index 9d8b8ea..1753bd1 100644 --- a/casic/face/CasicFaceInterface.h +++ b/casic/face/CasicFaceInterface.h @@ -52,7 +52,7 @@ cv::Rect faceDetectByCVCascade(cv::Mat frame, int minFaceSize); cv::Rect eyeDetectByCVCascade(cv::Mat frame); - bool hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize); + std::vector eyeDetectByCVCascade(cv::Mat frame, int minEyeSize); void setMinFaceSize(int minFaceSize); void setMinEyeSize(int minEyeSize); private: diff --git a/dao/RecognitionRecordDao.cpp b/dao/RecognitionRecordDao.cpp index 403894a..d7103f9 100644 --- a/dao/RecognitionRecordDao.cpp +++ b/dao/RecognitionRecordDao.cpp @@ -91,13 +91,14 @@ .arg(object.value("type").toString()) .arg(object.value("dev_code").toString()) .arg(object.value("door_code").toString()) - .arg(object.value("inout_type").toString()); + .arg(object.value("inout_type").toString()) + .arg(object.value("debug_info").toString()); query.prepare(sql); LOG(DEBUG) << sql.toStdString(); // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES ('%1', '%2')") + QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES ('%1', '%2')") .arg(id).arg(object.value("debug_info").toString()); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/device/CameraPositionController.cpp b/device/CameraPositionController.cpp new file mode 100644 index 0000000..577c9ad --- /dev/null +++ b/device/CameraPositionController.cpp @@ -0,0 +1,91 @@ +#include "CameraPositionController.h" + +CameraPositionController::CameraPositionController(QObject *parent) : QThread(parent) +{ + this->working = false; + this->exit = false; +} + +CameraPositionController::~CameraPositionController() +{ + this->setWorking(false); +} + +void CameraPositionController::setWorking(bool working) +{ + this->working = working; +} +void CameraPositionController::exitThread() +{ + this->working = false; + this->exit = true; +} + +void CameraPositionController::run() +{ + while (exit == false) + { + if (this->working == false) + { + this->msleep(200); // 200ms后再判断 + continue; + } + + // 取一幅图像 + cv::Mat rawFrame = ProMemory::getInstance().faceCam->takeOneRawFrame(); +/* + // 分类器找眼睛 + cv::Rect eyeRect = casic::face::CasicFaceInterface::getInstance().eyeDetectByCVCascade(rawFrame); + if (eyeRect.width != 0) + { + // 眼睛的位置 + int eyeCenter = eyeRect.y + eyeRect.height / 2; + LOG(DEBUG) << eyeCenter << " " << abs(eyeCenter - 300) << " " << 100 * abs(eyeCenter - 300) / 20 + 200; + + if (eyeCenter < 250 || eyeCenter > 350) + { +// ProMemory::getInstance().moto->autoPosition(eyeCenter); + emit motoControl(eyeCenter); + +// this->msleep(100 * abs(eyeCenter - 300) / 20 + 200); // 200ms后再判断 + } + } + */ + + // 分类器找脸 + cv::Rect faceRect = casic::face::CasicFaceInterface::getInstance().faceDetectByCVCascade(rawFrame, SettingConfig::getInstance().MIN_WORK_FACE_SIZE); + QString facePos = QString("%1 * %2, (%3, %4), (%5, %6)").arg(faceRect.width).arg(faceRect.height) + .arg(faceRect.x).arg(faceRect.y).arg(faceRect.x + faceRect.width).arg(faceRect.y + faceRect.height); + + if (faceRect.width != 0) + { + // 通过人脸的大小判断距离,提示靠近或者远离 + if (faceRect.width < 360) + { + emit updateTips(QString("距离太远,请靠近 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#9F1919"); + } else if (faceRect.width >= 360 && faceRect.width <= 480) + { + emit updateTips(QString("正在识别,请保持 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#248A53"); + + // 位置合适 开始识别 +// ProMemory::getInstance().irisRecogPro->setWorking(true); +// ProMemory::getInstance().irisCam->startCapture(); +// this->setWorking(false); + } else if (faceRect.width > 480) + { + emit updateTips(QString("距离太近,请远离 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#9F1919"); + } + } + + this->msleep(500); + } +} + + +void CameraPositionController::checkFacePosition() +{ + +} diff --git a/device/CameraPositionController.h b/device/CameraPositionController.h new file mode 100644 index 0000000..9520b14 --- /dev/null +++ b/device/CameraPositionController.h @@ -0,0 +1,39 @@ +#ifndef CAMERAPOSITIONCONTROLLER_H +#define CAMERAPOSITIONCONTROLLER_H + +#include +#include + +#include "opencv2/opencv.hpp" +#include "utils/UtilInclude.h" +#include "casic/ProMemory.h" + +class CameraPositionController : public QThread +{ + Q_OBJECT +public: + explicit CameraPositionController(QObject *parent = 0); + ~CameraPositionController(); + + void setWorking(bool working); + void exitThread(); + +protected: + //QThread的虚函数 + //线程处理函数 + //不能直接调用, 通过start()间接调用 + void run(); + + volatile bool working; + volatile bool exit; + +public slots: + void checkFacePosition(); + +signals: + void updateTips(QString tipsText); + void updateTipsBackgroundColor(QString bgColor); + void motoControl(int eyeCenter); +}; + +#endif // CAMERAPOSITIONCONTROLLER_H diff --git a/device/FaceCameraController.cpp b/device/FaceCameraController.cpp index 0fe4b4c..2a4d7cb 100644 --- a/device/FaceCameraController.cpp +++ b/device/FaceCameraController.cpp @@ -41,8 +41,7 @@ void FaceCameraController::closeFaceCamera() { faceCap->release(); - - delete faceCap; +// delete faceCap; } @@ -88,7 +87,7 @@ // 拍图 faceCap->read(faceMat); - LOG(TRACE) << "TAKE ONE FACE FRAME " << faceMat.cols << " * " << faceMat.rows; + LOG(TRACE) << QThread::currentThreadId() << " TAKE ONE FACE FRAME " << faceMat.cols << " * " << faceMat.rows; // 左右翻转 cv::Mat imageMatMiir; diff --git a/device/MotoController.cpp b/device/MotoController.cpp new file mode 100644 index 0000000..15cb5f0 --- /dev/null +++ b/device/MotoController.cpp @@ -0,0 +1,127 @@ +#include "MotoController.h" + + +MotoController::MotoController(QObject *parent) : QObject(parent) +{ + this->portName = "COM2"; + this->baudRate = "9600"; +} + + +bool MotoController::initSerialMCU() +{ + QList list = QSerialPortInfo::availablePorts(); + if (list.isEmpty() == true) + return false; + + this->portName = SettingConfig::getInstance().PORT_NAME; + + serial.setPortName(this->portName); + serial.setBaudRate(this->baudRate.toInt()); + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); + + bool succ = serial.open(QIODevice::ReadWrite); + + //连接信号和槽 + + LOG(DEBUG) << QString("[MotoController][initSerialMCU]打开电机串口[%1][%2][%3]").arg(portName).arg(baudRate).arg(succ).toStdString(); + + return succ; +} + +void MotoController::sendDataAutoEnding(QByteArray data) +{ + LOG(INFO) << QString("向串口发送数据[send] %1").arg(data.data()).toStdString(); + + // 加上0x0D 0x0A换行结束 + data.append(0x0D).append(0x0A); + serial.write(data); +} + + +/** + * @brief MotoController::encodeProtocol + * @param content + * @return + * 格式 +0000 00 长度=9 + * bit1 = +/- +表示向上运动 -表示向下运动 + * bit2-bit4 表示调整的量 + * bit5 开关灯控制量 + * bit6 空格 + * bit7-bit8 数值的累加和 + * bit9 空格 + */ +QByteArray MotoController::encodeProtocol(QString content) +{ + if (content.toInt() > 0) + { + content = "+" + content; + } + + // 调整数值的绝对值 三位数字 + int abs = content.mid(1, content.length()).toInt(); + + // 补齐3位数值 + if (abs < 10) + { + content.insert(1, "00"); + } else if (abs < 100) + { + content.insert(1, "0"); + } + + // 计算累加和 + int sum = 0; + for (int i = 0; i < content.mid(1, content.length()).length(); i++) + { + sum += content.mid(i + 1, 1).toInt(); + } + + // 格式化累加和字符串 + QString sumStr = QString::number(sum); + if (sumStr.length() == 1) + { + sumStr.prepend("0"); + } else if (sumStr.length() > 2) + { + sumStr = QString::number(sum).mid(0, 2); + } + + // 开关灯的控制量 = 0 + content.append("0"); + content = content.append(0x20).append(sumStr).append(0x20); + + return content.toUtf8(); +} + +void MotoController::autoFacePosition(CasicFaceInfo * faceInfo) +{ + if (faceInfo->hasFace == false) + { + return; + } + + const int centerLine = 300; + int faceTop = faceInfo->faceRecTL[1]; + int faceCenterLine = faceTop + faceInfo->face.pos.height / 2; + + int diff = (faceCenterLine - centerLine) * -0.8; + QByteArray data = this->encodeProtocol(QString::number(diff)); + this->sendDataAutoEnding(data); +} + +void MotoController::autoPosition(int eyeCenter) +{ + int center = 300; + int dir = eyeCenter > center ? -1 : 1; + int step = abs(eyeCenter - center) / 20; + for (int i = 0; i < step; i++) + { + QByteArray data = this->encodeProtocol(QString::number(20 * dir)); + this->sendDataAutoEnding(data); + QThread::msleep(100); + } +} diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp index f202cfe..bc8018b 100644 --- a/CasicBioRecWin.cpp +++ b/CasicBioRecWin.cpp @@ -6,7 +6,7 @@ , ui(new Ui::CasicBioRecWin) { // 打开外部可执行程序 - outExe = new QProcess(this); +// outExe = new QProcess(this); // outExe->start(SettingConfig::getInstance().OUT_EXE_FILE); ui->setupUi(this); @@ -31,6 +31,7 @@ initFaceRecogThread(); // 人脸识别线程 initIrisRegistThread(); // 虹膜注册线程 initIrisRecogThread(); // 虹膜识别线程 + initCameraPositionThread(); // 调整相机位置 // 初始化人脸相机控制 ProMemory::getInstance().faceCam = new FaceCameraController(this); @@ -49,6 +50,12 @@ connect(ProMemory::getInstance().irisCam->rightHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, addPersonForm, &AddPersonForm::drawIrisImageOnFrame); + // 初始化电机控制 + ProMemory::getInstance().moto = new MotoController(this); + ProMemory::getInstance().moto->initSerialMCU(); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::motoControl, + ProMemory::getInstance().moto, &MotoController::autoPosition); + // 打印日志 LOG(INFO) << QString("应用程序启动成功[Application Startup Success]").toStdString(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::MAIN_PAGE; @@ -72,6 +79,10 @@ ProMemory::getInstance().irisRecogPro->deleteLater(); ProMemory::getInstance().irisRecogPro->wait(); + ProMemory::getInstance().camPosCtrl->exitThread(); + ProMemory::getInstance().camPosCtrl->deleteLater(); + ProMemory::getInstance().camPosCtrl->wait(); + // 关闭自动启动的外部程序 // outExe->close(); // delete outExe; @@ -81,12 +92,14 @@ delete ProMemory::getInstance().faceRecogPro; delete ProMemory::getInstance().irisRegistPro; delete ProMemory::getInstance().irisRecogPro; + delete ProMemory::getInstance().camPosCtrl; } void CasicBioRecWin::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: + LOG(INFO) << "" << std::endl; QTimer::singleShot(100, qApp, SLOT(quit())); default: @@ -204,8 +217,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -244,8 +255,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -255,3 +264,17 @@ ProMemory::getInstance().irisRecogPro->start(); } + +void CasicBioRecWin::initCameraPositionThread() +{ + // 调整相机位置处理 + ProMemory::getInstance().camPosCtrl = new CameraPositionController(this); + + // 绑定信号与槽函数 + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTips, + recogResultForm, &RecognizeResultForm::updateRecogTips); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTipsBackgroundColor, + recogResultForm, &RecognizeResultForm::updateRecogTipsColor); + + ProMemory::getInstance().camPosCtrl->start(); +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h index b70245a..b5a3db9 100644 --- a/CasicBioRecWin.h +++ b/CasicBioRecWin.h @@ -54,6 +54,7 @@ void initFaceRecogThread(); void initIrisRegistThread(); void initIrisRecogThread(); + void initCameraPositionThread(); }; #endif // CASICBIORECWIN_H diff --git a/RecognizeResultForm.cpp b/RecognizeResultForm.cpp index e45a191..b340be9 100644 --- a/RecognizeResultForm.cpp +++ b/RecognizeResultForm.cpp @@ -20,7 +20,7 @@ RecognizeResultForm::~RecognizeResultForm() { - delete ui; + delete ui; } void RecognizeResultForm::startWorkingRecognize() @@ -29,23 +29,32 @@ switch (SettingConfig::getInstance().RECOG_TYPE) { case 1: // 人脸识别 + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); break; case 2: // 虹膜识别 + ProMemory::getInstance().clearIrisQueue(); +// ProMemory::getInstance().camPosCtrl->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; case 3: + // 双认证 先打开人脸识别 成功后再进行虹膜识别 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(true); + break; case 4: // 人脸和虹膜都需要打开 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; } - // 将界面切换到识别界面 RecognizeResultForm + // 开始拍图并显示视频 ProMemory::getInstance().faceCam->openFaceCamera(SettingConfig::getInstance().FACE_FRAME_INTERVAL); ui->labBackground->raise(); @@ -80,6 +89,14 @@ ui->widgetFail->raise(); ui->widgetFail->show(); + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().camPosCtrl->setWorking(false); + + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(false); + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ ui->labBackground->raise(); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -137,9 +154,9 @@ case 1: { // 仅人脸识别 - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); LOG(DEBUG) << QString("[RecognizeResultForm] 人脸识别成功 [%1]").arg(CasicFaceRecState::getInstance().toString()).toStdString(); @@ -158,9 +175,12 @@ case 2: { // 仅虹膜识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + // 停止控制电机和提示 + ProMemory::getInstance().camPosCtrl->setWorking(false); LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜识别成功 [%1]").arg(CasicIrisRecState::getInstance().toString()).toStdString(); @@ -179,13 +199,13 @@ case 4: { // 任意识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); QString logStr = QString("[RecognizeResultForm]%1识别成功[%2]"); if (faceOrIris == 1) @@ -213,42 +233,56 @@ if (faceOrIris == 1) { this->personIdByFace = personId; + + // 人脸识别成功后 开始进行虹膜识别 + // 1. 首先停止人脸识别 + ProMemory::getInstance().faceRecogPro->setWorking(false); + ProMemory::getInstance().clearFaceQueue(); + + // 2. 虹膜识别开始 + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().camPosCtrl->setWorking(true); } else if (faceOrIris == 2) { this->personIdByIris = personId; + + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) + { + // 只有一个成功的结果 需要等待下次 + return; + } else if (personIdByFace != personIdByIris) + { + // 人脸和虹膜识别的不是同一人 识别失败 + LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); + SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); + showRecogFailure(); + } else + { + LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); + showRecognizeResult(personId); + + // 识别记录存入数据库 + RecognitionRecordDao recDao; + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("type", "3"); + record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); + recDao.save(record); + } } - - if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) - { - // 只有一个成功的结果 需要等待下次 - return; - } else if (personIdByFace != personIdByIris) - { - // 人脸和虹膜识别的不是同一人 识别失败 - LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); - SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); - showRecogFailure(); - } else - { - LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); - showRecognizeResult(personId); - } - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - ProMemory::getInstance().clearFaceQueue(); - ProMemory::getInstance().faceRecogPro->setWorking(false); - ProMemory::getInstance().faceCam->stopTakingPhoto(); - - // 识别记录存入数据库 - RecognitionRecordDao recDao; - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("type", "4"); - record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); - recDao.save(record); } } + +void RecognizeResultForm::updateRecogTips(QString tipsText) +{ + ui->labTitle->setText(tipsText); +} +void RecognizeResultForm::updateRecogTipsColor(QString bgColor) +{ + ui->labTitle->setStyleSheet("background: " + bgColor); +} diff --git a/RecognizeResultForm.h b/RecognizeResultForm.h index 2c51865..65dd8ad 100644 --- a/RecognizeResultForm.h +++ b/RecognizeResultForm.h @@ -30,6 +30,8 @@ void startWorkingRecognize(); // 开始工作 void drawImageOnHomeForm(QImage imageDisp); + void updateRecogTips(QString tipsText); + void updateRecogTipsColor(QString bgColor); private: Ui::RecognizeResultForm *ui; diff --git a/StartupForm.cpp b/StartupForm.cpp index 16c4dfc..cf20de1 100644 --- a/StartupForm.cpp +++ b/StartupForm.cpp @@ -20,17 +20,23 @@ } // 设置弹簧的高度和宽度 - ui->vsTop->changeSize(0, 200); - ui->vsMidd->changeSize(0, 100); ui->hsLeft->changeSize(400, 0); ui->hsMidd->changeSize(150, 0); + // 绑定时间和日期的标签单击事件 单击即开始识别 + connect(ui->labDate, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + connect(ui->labTime, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + // 初始化更新界面的定时器 // 每秒执行一次 connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &StartupForm::updateDateAndTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, - this, &StartupForm::takeOneFrameForCheckStatus); +// connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, +// this, &StartupForm::takeOneFrameForCheckStatus); TimeCounterUtil::getInstance().clockCounter->start(1000); } diff --git a/StartupForm.h b/StartupForm.h index f2850e9..fc79be0 100644 --- a/StartupForm.h +++ b/StartupForm.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "casic/ProMemory.h" #include "utils/UtilInclude.h" diff --git a/StartupForm.ui b/StartupForm.ui index afb610f..de353f3 100644 --- a/StartupForm.ui +++ b/StartupForm.ui @@ -15,20 +15,7 @@ - - - Qt::Vertical - - - - 17 - 166 - - - - - - + TextLabel @@ -38,7 +25,7 @@ - + TextLabel @@ -48,19 +35,6 @@ - - - Qt::Vertical - - - - 17 - 167 - - - - - @@ -158,6 +132,13 @@ + + + QDblClickLabel + QLabel +
QDblClickLabel.h
+
+
diff --git a/casic/ProMemory.h b/casic/ProMemory.h index 3e9fbd4..02a14cf 100644 --- a/casic/ProMemory.h +++ b/casic/ProMemory.h @@ -16,6 +16,8 @@ #include "device/face/FaceRecogProcess.h" #include "device/iris/IrisRegistProcess.h" #include "device/iris/IrisRecogProcess.h" +#include "device/MotoController.h" +#include "device/CameraPositionController.h" class FaceCameraController; class IrisCameraController; @@ -23,6 +25,8 @@ class FaceRecogProcess; class IrisRegistProcess; class IrisRecogProcess; +class MotoController; +class CameraPositionController; class ProMemory { @@ -66,6 +70,10 @@ IrisRegistProcess * irisRegistPro; IrisRecogProcess * irisRecogPro; + MotoController * moto; + + CameraPositionController * camPosCtrl; + private: ProMemory(); diff --git a/casic/face/CasicFaceInterface.cpp b/casic/face/CasicFaceInterface.cpp index f530212..3cb2118 100644 --- a/casic/face/CasicFaceInterface.cpp +++ b/casic/face/CasicFaceInterface.cpp @@ -45,8 +45,6 @@ delete this->cascade; this->cascade = nullptr; } - - LOG(DEBUG) << "delete models in destructor"; } void casic::face::CasicFaceInterface::setDetectorModelPath(std::string detectorModelPath) @@ -384,6 +382,9 @@ cv::Size minRectSize(minFaceSize, minFaceSize); cv::Size maxRectSize(maxFaceSize, maxFaceSize); + QElapsedTimer timer; + timer.start(); + // ★分类器对象调用 cascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); @@ -391,6 +392,8 @@ { return cv::Rect(0, 0, 0, 0); } + + LOG(DEBUG) << QString("人脸分类检测算法[tm: %1 ms][%2, %3]").arg(timer.elapsed()).arg(rect.at(0).width).arg(rect.at(0).height).toStdString(); return rect.at(0); } @@ -424,7 +427,7 @@ return rect.at(0); } -bool casic::face::CasicFaceInterface::hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize) +std::vector casic::face::CasicFaceInterface::eyeDetectByCVCascade(cv::Mat frame, int minEyeSize) { // 构建openCV自带的眼睛分类器 if (this->eyeCascade == nullptr) @@ -433,14 +436,14 @@ this->eyeCascade->load(cvEyeCascadeName); } - std::vector rect; + std::vector rectVec; cv::Size minRectSize(minEyeSize, minEyeSize); cv::Size maxRectSize(maxEyeSize, maxEyeSize); // ★分类器对象调用 - eyeCascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); + eyeCascade->detectMultiScale(frame, rectVec, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); - return rect.size() == 0 ? false : true; + return rectVec; } void casic::face::CasicFaceInterface::setMinFaceSize(int minFaceSize) diff --git a/casic/face/CasicFaceInterface.h b/casic/face/CasicFaceInterface.h index 9d8b8ea..1753bd1 100644 --- a/casic/face/CasicFaceInterface.h +++ b/casic/face/CasicFaceInterface.h @@ -52,7 +52,7 @@ cv::Rect faceDetectByCVCascade(cv::Mat frame, int minFaceSize); cv::Rect eyeDetectByCVCascade(cv::Mat frame); - bool hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize); + std::vector eyeDetectByCVCascade(cv::Mat frame, int minEyeSize); void setMinFaceSize(int minFaceSize); void setMinEyeSize(int minEyeSize); private: diff --git a/dao/RecognitionRecordDao.cpp b/dao/RecognitionRecordDao.cpp index 403894a..d7103f9 100644 --- a/dao/RecognitionRecordDao.cpp +++ b/dao/RecognitionRecordDao.cpp @@ -91,13 +91,14 @@ .arg(object.value("type").toString()) .arg(object.value("dev_code").toString()) .arg(object.value("door_code").toString()) - .arg(object.value("inout_type").toString()); + .arg(object.value("inout_type").toString()) + .arg(object.value("debug_info").toString()); query.prepare(sql); LOG(DEBUG) << sql.toStdString(); // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES ('%1', '%2')") + QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES ('%1', '%2')") .arg(id).arg(object.value("debug_info").toString()); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/device/CameraPositionController.cpp b/device/CameraPositionController.cpp new file mode 100644 index 0000000..577c9ad --- /dev/null +++ b/device/CameraPositionController.cpp @@ -0,0 +1,91 @@ +#include "CameraPositionController.h" + +CameraPositionController::CameraPositionController(QObject *parent) : QThread(parent) +{ + this->working = false; + this->exit = false; +} + +CameraPositionController::~CameraPositionController() +{ + this->setWorking(false); +} + +void CameraPositionController::setWorking(bool working) +{ + this->working = working; +} +void CameraPositionController::exitThread() +{ + this->working = false; + this->exit = true; +} + +void CameraPositionController::run() +{ + while (exit == false) + { + if (this->working == false) + { + this->msleep(200); // 200ms后再判断 + continue; + } + + // 取一幅图像 + cv::Mat rawFrame = ProMemory::getInstance().faceCam->takeOneRawFrame(); +/* + // 分类器找眼睛 + cv::Rect eyeRect = casic::face::CasicFaceInterface::getInstance().eyeDetectByCVCascade(rawFrame); + if (eyeRect.width != 0) + { + // 眼睛的位置 + int eyeCenter = eyeRect.y + eyeRect.height / 2; + LOG(DEBUG) << eyeCenter << " " << abs(eyeCenter - 300) << " " << 100 * abs(eyeCenter - 300) / 20 + 200; + + if (eyeCenter < 250 || eyeCenter > 350) + { +// ProMemory::getInstance().moto->autoPosition(eyeCenter); + emit motoControl(eyeCenter); + +// this->msleep(100 * abs(eyeCenter - 300) / 20 + 200); // 200ms后再判断 + } + } + */ + + // 分类器找脸 + cv::Rect faceRect = casic::face::CasicFaceInterface::getInstance().faceDetectByCVCascade(rawFrame, SettingConfig::getInstance().MIN_WORK_FACE_SIZE); + QString facePos = QString("%1 * %2, (%3, %4), (%5, %6)").arg(faceRect.width).arg(faceRect.height) + .arg(faceRect.x).arg(faceRect.y).arg(faceRect.x + faceRect.width).arg(faceRect.y + faceRect.height); + + if (faceRect.width != 0) + { + // 通过人脸的大小判断距离,提示靠近或者远离 + if (faceRect.width < 360) + { + emit updateTips(QString("距离太远,请靠近 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#9F1919"); + } else if (faceRect.width >= 360 && faceRect.width <= 480) + { + emit updateTips(QString("正在识别,请保持 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#248A53"); + + // 位置合适 开始识别 +// ProMemory::getInstance().irisRecogPro->setWorking(true); +// ProMemory::getInstance().irisCam->startCapture(); +// this->setWorking(false); + } else if (faceRect.width > 480) + { + emit updateTips(QString("距离太近,请远离 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#9F1919"); + } + } + + this->msleep(500); + } +} + + +void CameraPositionController::checkFacePosition() +{ + +} diff --git a/device/CameraPositionController.h b/device/CameraPositionController.h new file mode 100644 index 0000000..9520b14 --- /dev/null +++ b/device/CameraPositionController.h @@ -0,0 +1,39 @@ +#ifndef CAMERAPOSITIONCONTROLLER_H +#define CAMERAPOSITIONCONTROLLER_H + +#include +#include + +#include "opencv2/opencv.hpp" +#include "utils/UtilInclude.h" +#include "casic/ProMemory.h" + +class CameraPositionController : public QThread +{ + Q_OBJECT +public: + explicit CameraPositionController(QObject *parent = 0); + ~CameraPositionController(); + + void setWorking(bool working); + void exitThread(); + +protected: + //QThread的虚函数 + //线程处理函数 + //不能直接调用, 通过start()间接调用 + void run(); + + volatile bool working; + volatile bool exit; + +public slots: + void checkFacePosition(); + +signals: + void updateTips(QString tipsText); + void updateTipsBackgroundColor(QString bgColor); + void motoControl(int eyeCenter); +}; + +#endif // CAMERAPOSITIONCONTROLLER_H diff --git a/device/FaceCameraController.cpp b/device/FaceCameraController.cpp index 0fe4b4c..2a4d7cb 100644 --- a/device/FaceCameraController.cpp +++ b/device/FaceCameraController.cpp @@ -41,8 +41,7 @@ void FaceCameraController::closeFaceCamera() { faceCap->release(); - - delete faceCap; +// delete faceCap; } @@ -88,7 +87,7 @@ // 拍图 faceCap->read(faceMat); - LOG(TRACE) << "TAKE ONE FACE FRAME " << faceMat.cols << " * " << faceMat.rows; + LOG(TRACE) << QThread::currentThreadId() << " TAKE ONE FACE FRAME " << faceMat.cols << " * " << faceMat.rows; // 左右翻转 cv::Mat imageMatMiir; diff --git a/device/MotoController.cpp b/device/MotoController.cpp new file mode 100644 index 0000000..15cb5f0 --- /dev/null +++ b/device/MotoController.cpp @@ -0,0 +1,127 @@ +#include "MotoController.h" + + +MotoController::MotoController(QObject *parent) : QObject(parent) +{ + this->portName = "COM2"; + this->baudRate = "9600"; +} + + +bool MotoController::initSerialMCU() +{ + QList list = QSerialPortInfo::availablePorts(); + if (list.isEmpty() == true) + return false; + + this->portName = SettingConfig::getInstance().PORT_NAME; + + serial.setPortName(this->portName); + serial.setBaudRate(this->baudRate.toInt()); + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); + + bool succ = serial.open(QIODevice::ReadWrite); + + //连接信号和槽 + + LOG(DEBUG) << QString("[MotoController][initSerialMCU]打开电机串口[%1][%2][%3]").arg(portName).arg(baudRate).arg(succ).toStdString(); + + return succ; +} + +void MotoController::sendDataAutoEnding(QByteArray data) +{ + LOG(INFO) << QString("向串口发送数据[send] %1").arg(data.data()).toStdString(); + + // 加上0x0D 0x0A换行结束 + data.append(0x0D).append(0x0A); + serial.write(data); +} + + +/** + * @brief MotoController::encodeProtocol + * @param content + * @return + * 格式 +0000 00 长度=9 + * bit1 = +/- +表示向上运动 -表示向下运动 + * bit2-bit4 表示调整的量 + * bit5 开关灯控制量 + * bit6 空格 + * bit7-bit8 数值的累加和 + * bit9 空格 + */ +QByteArray MotoController::encodeProtocol(QString content) +{ + if (content.toInt() > 0) + { + content = "+" + content; + } + + // 调整数值的绝对值 三位数字 + int abs = content.mid(1, content.length()).toInt(); + + // 补齐3位数值 + if (abs < 10) + { + content.insert(1, "00"); + } else if (abs < 100) + { + content.insert(1, "0"); + } + + // 计算累加和 + int sum = 0; + for (int i = 0; i < content.mid(1, content.length()).length(); i++) + { + sum += content.mid(i + 1, 1).toInt(); + } + + // 格式化累加和字符串 + QString sumStr = QString::number(sum); + if (sumStr.length() == 1) + { + sumStr.prepend("0"); + } else if (sumStr.length() > 2) + { + sumStr = QString::number(sum).mid(0, 2); + } + + // 开关灯的控制量 = 0 + content.append("0"); + content = content.append(0x20).append(sumStr).append(0x20); + + return content.toUtf8(); +} + +void MotoController::autoFacePosition(CasicFaceInfo * faceInfo) +{ + if (faceInfo->hasFace == false) + { + return; + } + + const int centerLine = 300; + int faceTop = faceInfo->faceRecTL[1]; + int faceCenterLine = faceTop + faceInfo->face.pos.height / 2; + + int diff = (faceCenterLine - centerLine) * -0.8; + QByteArray data = this->encodeProtocol(QString::number(diff)); + this->sendDataAutoEnding(data); +} + +void MotoController::autoPosition(int eyeCenter) +{ + int center = 300; + int dir = eyeCenter > center ? -1 : 1; + int step = abs(eyeCenter - center) / 20; + for (int i = 0; i < step; i++) + { + QByteArray data = this->encodeProtocol(QString::number(20 * dir)); + this->sendDataAutoEnding(data); + QThread::msleep(100); + } +} diff --git a/device/MotoController.h b/device/MotoController.h new file mode 100644 index 0000000..60aa5dc --- /dev/null +++ b/device/MotoController.h @@ -0,0 +1,39 @@ +#ifndef MOTOCONTROLLER_H +#define MOTOCONTROLLER_H + +#include +#include +#include +#include + +#include "casic/face/CasicFaceInfo.h" +#include "utils/UtilInclude.h" + +class MotoController : public QObject +{ + Q_OBJECT +public: + explicit MotoController(QObject *parent = nullptr); + + // 打开串口 + bool initSerialMCU(); + +public slots: + void autoFacePosition(CasicFaceInfo * faceInfo); + void autoPosition(int eyeCenter); + +private: + QSerialPort serial; + QString portName; + QString baudRate; + + QByteArray buffRecv; + + QByteArray encodeProtocol(QString content); + void sendDataAutoEnding(QByteArray data); + +signals: + +}; + +#endif // MOTOCONTROLLER_H diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp index f202cfe..bc8018b 100644 --- a/CasicBioRecWin.cpp +++ b/CasicBioRecWin.cpp @@ -6,7 +6,7 @@ , ui(new Ui::CasicBioRecWin) { // 打开外部可执行程序 - outExe = new QProcess(this); +// outExe = new QProcess(this); // outExe->start(SettingConfig::getInstance().OUT_EXE_FILE); ui->setupUi(this); @@ -31,6 +31,7 @@ initFaceRecogThread(); // 人脸识别线程 initIrisRegistThread(); // 虹膜注册线程 initIrisRecogThread(); // 虹膜识别线程 + initCameraPositionThread(); // 调整相机位置 // 初始化人脸相机控制 ProMemory::getInstance().faceCam = new FaceCameraController(this); @@ -49,6 +50,12 @@ connect(ProMemory::getInstance().irisCam->rightHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, addPersonForm, &AddPersonForm::drawIrisImageOnFrame); + // 初始化电机控制 + ProMemory::getInstance().moto = new MotoController(this); + ProMemory::getInstance().moto->initSerialMCU(); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::motoControl, + ProMemory::getInstance().moto, &MotoController::autoPosition); + // 打印日志 LOG(INFO) << QString("应用程序启动成功[Application Startup Success]").toStdString(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::MAIN_PAGE; @@ -72,6 +79,10 @@ ProMemory::getInstance().irisRecogPro->deleteLater(); ProMemory::getInstance().irisRecogPro->wait(); + ProMemory::getInstance().camPosCtrl->exitThread(); + ProMemory::getInstance().camPosCtrl->deleteLater(); + ProMemory::getInstance().camPosCtrl->wait(); + // 关闭自动启动的外部程序 // outExe->close(); // delete outExe; @@ -81,12 +92,14 @@ delete ProMemory::getInstance().faceRecogPro; delete ProMemory::getInstance().irisRegistPro; delete ProMemory::getInstance().irisRecogPro; + delete ProMemory::getInstance().camPosCtrl; } void CasicBioRecWin::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: + LOG(INFO) << "" << std::endl; QTimer::singleShot(100, qApp, SLOT(quit())); default: @@ -204,8 +217,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -244,8 +255,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -255,3 +264,17 @@ ProMemory::getInstance().irisRecogPro->start(); } + +void CasicBioRecWin::initCameraPositionThread() +{ + // 调整相机位置处理 + ProMemory::getInstance().camPosCtrl = new CameraPositionController(this); + + // 绑定信号与槽函数 + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTips, + recogResultForm, &RecognizeResultForm::updateRecogTips); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTipsBackgroundColor, + recogResultForm, &RecognizeResultForm::updateRecogTipsColor); + + ProMemory::getInstance().camPosCtrl->start(); +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h index b70245a..b5a3db9 100644 --- a/CasicBioRecWin.h +++ b/CasicBioRecWin.h @@ -54,6 +54,7 @@ void initFaceRecogThread(); void initIrisRegistThread(); void initIrisRecogThread(); + void initCameraPositionThread(); }; #endif // CASICBIORECWIN_H diff --git a/RecognizeResultForm.cpp b/RecognizeResultForm.cpp index e45a191..b340be9 100644 --- a/RecognizeResultForm.cpp +++ b/RecognizeResultForm.cpp @@ -20,7 +20,7 @@ RecognizeResultForm::~RecognizeResultForm() { - delete ui; + delete ui; } void RecognizeResultForm::startWorkingRecognize() @@ -29,23 +29,32 @@ switch (SettingConfig::getInstance().RECOG_TYPE) { case 1: // 人脸识别 + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); break; case 2: // 虹膜识别 + ProMemory::getInstance().clearIrisQueue(); +// ProMemory::getInstance().camPosCtrl->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; case 3: + // 双认证 先打开人脸识别 成功后再进行虹膜识别 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(true); + break; case 4: // 人脸和虹膜都需要打开 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; } - // 将界面切换到识别界面 RecognizeResultForm + // 开始拍图并显示视频 ProMemory::getInstance().faceCam->openFaceCamera(SettingConfig::getInstance().FACE_FRAME_INTERVAL); ui->labBackground->raise(); @@ -80,6 +89,14 @@ ui->widgetFail->raise(); ui->widgetFail->show(); + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().camPosCtrl->setWorking(false); + + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(false); + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ ui->labBackground->raise(); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -137,9 +154,9 @@ case 1: { // 仅人脸识别 - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); LOG(DEBUG) << QString("[RecognizeResultForm] 人脸识别成功 [%1]").arg(CasicFaceRecState::getInstance().toString()).toStdString(); @@ -158,9 +175,12 @@ case 2: { // 仅虹膜识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + // 停止控制电机和提示 + ProMemory::getInstance().camPosCtrl->setWorking(false); LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜识别成功 [%1]").arg(CasicIrisRecState::getInstance().toString()).toStdString(); @@ -179,13 +199,13 @@ case 4: { // 任意识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); QString logStr = QString("[RecognizeResultForm]%1识别成功[%2]"); if (faceOrIris == 1) @@ -213,42 +233,56 @@ if (faceOrIris == 1) { this->personIdByFace = personId; + + // 人脸识别成功后 开始进行虹膜识别 + // 1. 首先停止人脸识别 + ProMemory::getInstance().faceRecogPro->setWorking(false); + ProMemory::getInstance().clearFaceQueue(); + + // 2. 虹膜识别开始 + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().camPosCtrl->setWorking(true); } else if (faceOrIris == 2) { this->personIdByIris = personId; + + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) + { + // 只有一个成功的结果 需要等待下次 + return; + } else if (personIdByFace != personIdByIris) + { + // 人脸和虹膜识别的不是同一人 识别失败 + LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); + SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); + showRecogFailure(); + } else + { + LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); + showRecognizeResult(personId); + + // 识别记录存入数据库 + RecognitionRecordDao recDao; + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("type", "3"); + record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); + recDao.save(record); + } } - - if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) - { - // 只有一个成功的结果 需要等待下次 - return; - } else if (personIdByFace != personIdByIris) - { - // 人脸和虹膜识别的不是同一人 识别失败 - LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); - SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); - showRecogFailure(); - } else - { - LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); - showRecognizeResult(personId); - } - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - ProMemory::getInstance().clearFaceQueue(); - ProMemory::getInstance().faceRecogPro->setWorking(false); - ProMemory::getInstance().faceCam->stopTakingPhoto(); - - // 识别记录存入数据库 - RecognitionRecordDao recDao; - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("type", "4"); - record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); - recDao.save(record); } } + +void RecognizeResultForm::updateRecogTips(QString tipsText) +{ + ui->labTitle->setText(tipsText); +} +void RecognizeResultForm::updateRecogTipsColor(QString bgColor) +{ + ui->labTitle->setStyleSheet("background: " + bgColor); +} diff --git a/RecognizeResultForm.h b/RecognizeResultForm.h index 2c51865..65dd8ad 100644 --- a/RecognizeResultForm.h +++ b/RecognizeResultForm.h @@ -30,6 +30,8 @@ void startWorkingRecognize(); // 开始工作 void drawImageOnHomeForm(QImage imageDisp); + void updateRecogTips(QString tipsText); + void updateRecogTipsColor(QString bgColor); private: Ui::RecognizeResultForm *ui; diff --git a/StartupForm.cpp b/StartupForm.cpp index 16c4dfc..cf20de1 100644 --- a/StartupForm.cpp +++ b/StartupForm.cpp @@ -20,17 +20,23 @@ } // 设置弹簧的高度和宽度 - ui->vsTop->changeSize(0, 200); - ui->vsMidd->changeSize(0, 100); ui->hsLeft->changeSize(400, 0); ui->hsMidd->changeSize(150, 0); + // 绑定时间和日期的标签单击事件 单击即开始识别 + connect(ui->labDate, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + connect(ui->labTime, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + // 初始化更新界面的定时器 // 每秒执行一次 connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &StartupForm::updateDateAndTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, - this, &StartupForm::takeOneFrameForCheckStatus); +// connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, +// this, &StartupForm::takeOneFrameForCheckStatus); TimeCounterUtil::getInstance().clockCounter->start(1000); } diff --git a/StartupForm.h b/StartupForm.h index f2850e9..fc79be0 100644 --- a/StartupForm.h +++ b/StartupForm.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "casic/ProMemory.h" #include "utils/UtilInclude.h" diff --git a/StartupForm.ui b/StartupForm.ui index afb610f..de353f3 100644 --- a/StartupForm.ui +++ b/StartupForm.ui @@ -15,20 +15,7 @@ - - - Qt::Vertical - - - - 17 - 166 - - - - - - + TextLabel @@ -38,7 +25,7 @@ - + TextLabel @@ -48,19 +35,6 @@ - - - Qt::Vertical - - - - 17 - 167 - - - - - @@ -158,6 +132,13 @@ + + + QDblClickLabel + QLabel +
QDblClickLabel.h
+
+
diff --git a/casic/ProMemory.h b/casic/ProMemory.h index 3e9fbd4..02a14cf 100644 --- a/casic/ProMemory.h +++ b/casic/ProMemory.h @@ -16,6 +16,8 @@ #include "device/face/FaceRecogProcess.h" #include "device/iris/IrisRegistProcess.h" #include "device/iris/IrisRecogProcess.h" +#include "device/MotoController.h" +#include "device/CameraPositionController.h" class FaceCameraController; class IrisCameraController; @@ -23,6 +25,8 @@ class FaceRecogProcess; class IrisRegistProcess; class IrisRecogProcess; +class MotoController; +class CameraPositionController; class ProMemory { @@ -66,6 +70,10 @@ IrisRegistProcess * irisRegistPro; IrisRecogProcess * irisRecogPro; + MotoController * moto; + + CameraPositionController * camPosCtrl; + private: ProMemory(); diff --git a/casic/face/CasicFaceInterface.cpp b/casic/face/CasicFaceInterface.cpp index f530212..3cb2118 100644 --- a/casic/face/CasicFaceInterface.cpp +++ b/casic/face/CasicFaceInterface.cpp @@ -45,8 +45,6 @@ delete this->cascade; this->cascade = nullptr; } - - LOG(DEBUG) << "delete models in destructor"; } void casic::face::CasicFaceInterface::setDetectorModelPath(std::string detectorModelPath) @@ -384,6 +382,9 @@ cv::Size minRectSize(minFaceSize, minFaceSize); cv::Size maxRectSize(maxFaceSize, maxFaceSize); + QElapsedTimer timer; + timer.start(); + // ★分类器对象调用 cascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); @@ -391,6 +392,8 @@ { return cv::Rect(0, 0, 0, 0); } + + LOG(DEBUG) << QString("人脸分类检测算法[tm: %1 ms][%2, %3]").arg(timer.elapsed()).arg(rect.at(0).width).arg(rect.at(0).height).toStdString(); return rect.at(0); } @@ -424,7 +427,7 @@ return rect.at(0); } -bool casic::face::CasicFaceInterface::hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize) +std::vector casic::face::CasicFaceInterface::eyeDetectByCVCascade(cv::Mat frame, int minEyeSize) { // 构建openCV自带的眼睛分类器 if (this->eyeCascade == nullptr) @@ -433,14 +436,14 @@ this->eyeCascade->load(cvEyeCascadeName); } - std::vector rect; + std::vector rectVec; cv::Size minRectSize(minEyeSize, minEyeSize); cv::Size maxRectSize(maxEyeSize, maxEyeSize); // ★分类器对象调用 - eyeCascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); + eyeCascade->detectMultiScale(frame, rectVec, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); - return rect.size() == 0 ? false : true; + return rectVec; } void casic::face::CasicFaceInterface::setMinFaceSize(int minFaceSize) diff --git a/casic/face/CasicFaceInterface.h b/casic/face/CasicFaceInterface.h index 9d8b8ea..1753bd1 100644 --- a/casic/face/CasicFaceInterface.h +++ b/casic/face/CasicFaceInterface.h @@ -52,7 +52,7 @@ cv::Rect faceDetectByCVCascade(cv::Mat frame, int minFaceSize); cv::Rect eyeDetectByCVCascade(cv::Mat frame); - bool hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize); + std::vector eyeDetectByCVCascade(cv::Mat frame, int minEyeSize); void setMinFaceSize(int minFaceSize); void setMinEyeSize(int minEyeSize); private: diff --git a/dao/RecognitionRecordDao.cpp b/dao/RecognitionRecordDao.cpp index 403894a..d7103f9 100644 --- a/dao/RecognitionRecordDao.cpp +++ b/dao/RecognitionRecordDao.cpp @@ -91,13 +91,14 @@ .arg(object.value("type").toString()) .arg(object.value("dev_code").toString()) .arg(object.value("door_code").toString()) - .arg(object.value("inout_type").toString()); + .arg(object.value("inout_type").toString()) + .arg(object.value("debug_info").toString()); query.prepare(sql); LOG(DEBUG) << sql.toStdString(); // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES ('%1', '%2')") + QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES ('%1', '%2')") .arg(id).arg(object.value("debug_info").toString()); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/device/CameraPositionController.cpp b/device/CameraPositionController.cpp new file mode 100644 index 0000000..577c9ad --- /dev/null +++ b/device/CameraPositionController.cpp @@ -0,0 +1,91 @@ +#include "CameraPositionController.h" + +CameraPositionController::CameraPositionController(QObject *parent) : QThread(parent) +{ + this->working = false; + this->exit = false; +} + +CameraPositionController::~CameraPositionController() +{ + this->setWorking(false); +} + +void CameraPositionController::setWorking(bool working) +{ + this->working = working; +} +void CameraPositionController::exitThread() +{ + this->working = false; + this->exit = true; +} + +void CameraPositionController::run() +{ + while (exit == false) + { + if (this->working == false) + { + this->msleep(200); // 200ms后再判断 + continue; + } + + // 取一幅图像 + cv::Mat rawFrame = ProMemory::getInstance().faceCam->takeOneRawFrame(); +/* + // 分类器找眼睛 + cv::Rect eyeRect = casic::face::CasicFaceInterface::getInstance().eyeDetectByCVCascade(rawFrame); + if (eyeRect.width != 0) + { + // 眼睛的位置 + int eyeCenter = eyeRect.y + eyeRect.height / 2; + LOG(DEBUG) << eyeCenter << " " << abs(eyeCenter - 300) << " " << 100 * abs(eyeCenter - 300) / 20 + 200; + + if (eyeCenter < 250 || eyeCenter > 350) + { +// ProMemory::getInstance().moto->autoPosition(eyeCenter); + emit motoControl(eyeCenter); + +// this->msleep(100 * abs(eyeCenter - 300) / 20 + 200); // 200ms后再判断 + } + } + */ + + // 分类器找脸 + cv::Rect faceRect = casic::face::CasicFaceInterface::getInstance().faceDetectByCVCascade(rawFrame, SettingConfig::getInstance().MIN_WORK_FACE_SIZE); + QString facePos = QString("%1 * %2, (%3, %4), (%5, %6)").arg(faceRect.width).arg(faceRect.height) + .arg(faceRect.x).arg(faceRect.y).arg(faceRect.x + faceRect.width).arg(faceRect.y + faceRect.height); + + if (faceRect.width != 0) + { + // 通过人脸的大小判断距离,提示靠近或者远离 + if (faceRect.width < 360) + { + emit updateTips(QString("距离太远,请靠近 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#9F1919"); + } else if (faceRect.width >= 360 && faceRect.width <= 480) + { + emit updateTips(QString("正在识别,请保持 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#248A53"); + + // 位置合适 开始识别 +// ProMemory::getInstance().irisRecogPro->setWorking(true); +// ProMemory::getInstance().irisCam->startCapture(); +// this->setWorking(false); + } else if (faceRect.width > 480) + { + emit updateTips(QString("距离太近,请远离 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#9F1919"); + } + } + + this->msleep(500); + } +} + + +void CameraPositionController::checkFacePosition() +{ + +} diff --git a/device/CameraPositionController.h b/device/CameraPositionController.h new file mode 100644 index 0000000..9520b14 --- /dev/null +++ b/device/CameraPositionController.h @@ -0,0 +1,39 @@ +#ifndef CAMERAPOSITIONCONTROLLER_H +#define CAMERAPOSITIONCONTROLLER_H + +#include +#include + +#include "opencv2/opencv.hpp" +#include "utils/UtilInclude.h" +#include "casic/ProMemory.h" + +class CameraPositionController : public QThread +{ + Q_OBJECT +public: + explicit CameraPositionController(QObject *parent = 0); + ~CameraPositionController(); + + void setWorking(bool working); + void exitThread(); + +protected: + //QThread的虚函数 + //线程处理函数 + //不能直接调用, 通过start()间接调用 + void run(); + + volatile bool working; + volatile bool exit; + +public slots: + void checkFacePosition(); + +signals: + void updateTips(QString tipsText); + void updateTipsBackgroundColor(QString bgColor); + void motoControl(int eyeCenter); +}; + +#endif // CAMERAPOSITIONCONTROLLER_H diff --git a/device/FaceCameraController.cpp b/device/FaceCameraController.cpp index 0fe4b4c..2a4d7cb 100644 --- a/device/FaceCameraController.cpp +++ b/device/FaceCameraController.cpp @@ -41,8 +41,7 @@ void FaceCameraController::closeFaceCamera() { faceCap->release(); - - delete faceCap; +// delete faceCap; } @@ -88,7 +87,7 @@ // 拍图 faceCap->read(faceMat); - LOG(TRACE) << "TAKE ONE FACE FRAME " << faceMat.cols << " * " << faceMat.rows; + LOG(TRACE) << QThread::currentThreadId() << " TAKE ONE FACE FRAME " << faceMat.cols << " * " << faceMat.rows; // 左右翻转 cv::Mat imageMatMiir; diff --git a/device/MotoController.cpp b/device/MotoController.cpp new file mode 100644 index 0000000..15cb5f0 --- /dev/null +++ b/device/MotoController.cpp @@ -0,0 +1,127 @@ +#include "MotoController.h" + + +MotoController::MotoController(QObject *parent) : QObject(parent) +{ + this->portName = "COM2"; + this->baudRate = "9600"; +} + + +bool MotoController::initSerialMCU() +{ + QList list = QSerialPortInfo::availablePorts(); + if (list.isEmpty() == true) + return false; + + this->portName = SettingConfig::getInstance().PORT_NAME; + + serial.setPortName(this->portName); + serial.setBaudRate(this->baudRate.toInt()); + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); + + bool succ = serial.open(QIODevice::ReadWrite); + + //连接信号和槽 + + LOG(DEBUG) << QString("[MotoController][initSerialMCU]打开电机串口[%1][%2][%3]").arg(portName).arg(baudRate).arg(succ).toStdString(); + + return succ; +} + +void MotoController::sendDataAutoEnding(QByteArray data) +{ + LOG(INFO) << QString("向串口发送数据[send] %1").arg(data.data()).toStdString(); + + // 加上0x0D 0x0A换行结束 + data.append(0x0D).append(0x0A); + serial.write(data); +} + + +/** + * @brief MotoController::encodeProtocol + * @param content + * @return + * 格式 +0000 00 长度=9 + * bit1 = +/- +表示向上运动 -表示向下运动 + * bit2-bit4 表示调整的量 + * bit5 开关灯控制量 + * bit6 空格 + * bit7-bit8 数值的累加和 + * bit9 空格 + */ +QByteArray MotoController::encodeProtocol(QString content) +{ + if (content.toInt() > 0) + { + content = "+" + content; + } + + // 调整数值的绝对值 三位数字 + int abs = content.mid(1, content.length()).toInt(); + + // 补齐3位数值 + if (abs < 10) + { + content.insert(1, "00"); + } else if (abs < 100) + { + content.insert(1, "0"); + } + + // 计算累加和 + int sum = 0; + for (int i = 0; i < content.mid(1, content.length()).length(); i++) + { + sum += content.mid(i + 1, 1).toInt(); + } + + // 格式化累加和字符串 + QString sumStr = QString::number(sum); + if (sumStr.length() == 1) + { + sumStr.prepend("0"); + } else if (sumStr.length() > 2) + { + sumStr = QString::number(sum).mid(0, 2); + } + + // 开关灯的控制量 = 0 + content.append("0"); + content = content.append(0x20).append(sumStr).append(0x20); + + return content.toUtf8(); +} + +void MotoController::autoFacePosition(CasicFaceInfo * faceInfo) +{ + if (faceInfo->hasFace == false) + { + return; + } + + const int centerLine = 300; + int faceTop = faceInfo->faceRecTL[1]; + int faceCenterLine = faceTop + faceInfo->face.pos.height / 2; + + int diff = (faceCenterLine - centerLine) * -0.8; + QByteArray data = this->encodeProtocol(QString::number(diff)); + this->sendDataAutoEnding(data); +} + +void MotoController::autoPosition(int eyeCenter) +{ + int center = 300; + int dir = eyeCenter > center ? -1 : 1; + int step = abs(eyeCenter - center) / 20; + for (int i = 0; i < step; i++) + { + QByteArray data = this->encodeProtocol(QString::number(20 * dir)); + this->sendDataAutoEnding(data); + QThread::msleep(100); + } +} diff --git a/device/MotoController.h b/device/MotoController.h new file mode 100644 index 0000000..60aa5dc --- /dev/null +++ b/device/MotoController.h @@ -0,0 +1,39 @@ +#ifndef MOTOCONTROLLER_H +#define MOTOCONTROLLER_H + +#include +#include +#include +#include + +#include "casic/face/CasicFaceInfo.h" +#include "utils/UtilInclude.h" + +class MotoController : public QObject +{ + Q_OBJECT +public: + explicit MotoController(QObject *parent = nullptr); + + // 打开串口 + bool initSerialMCU(); + +public slots: + void autoFacePosition(CasicFaceInfo * faceInfo); + void autoPosition(int eyeCenter); + +private: + QSerialPort serial; + QString portName; + QString baudRate; + + QByteArray buffRecv; + + QByteArray encodeProtocol(QString content); + void sendDataAutoEnding(QByteArray data); + +signals: + +}; + +#endif // MOTOCONTROLLER_H diff --git a/device/device.pri b/device/device.pri index 64e6e17..2a1b90b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,10 +1,12 @@ -HEADERS += $$PWD/FaceCameraController.h +HEADERS += $$PWD/FaceCameraController.h \ + $$PWD/CameraPositionController.h HEADERS += $$PWD/face/FaceRecogProcess.h HEADERS += $$PWD/face/FaceRegistProcess.h HEADERS += $$PWD/face/CasicFaceRecState.h -SOURCES += $$PWD/FaceCameraController.cpp +SOURCES += $$PWD/FaceCameraController.cpp \ + $$PWD/CameraPositionController.cpp SOURCES += $$PWD/face/FaceRecogProcess.cpp SOURCES += $$PWD/face/FaceRegistProcess.cpp SOURCES += $$PWD/face/CasicFaceRecState.cpp @@ -14,11 +16,14 @@ HEADERS += $$PWD/iris/IrisRegistProcess.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h -#HEADERS += $$PWD/MotoController.h SOURCES += $$PWD/IrisCameraController.cpp SOURCES += $$PWD/IrisCameraCapEventHandler.cpp SOURCES += $$PWD/iris/IrisRegistProcess.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp -#SOURCES += $$PWD/MotoController.cpp + +HEADERS += $$PWD/MotoController.h +SOURCES += $$PWD/MotoController.cpp +HEADERS += +SOURCES += diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp index f202cfe..bc8018b 100644 --- a/CasicBioRecWin.cpp +++ b/CasicBioRecWin.cpp @@ -6,7 +6,7 @@ , ui(new Ui::CasicBioRecWin) { // 打开外部可执行程序 - outExe = new QProcess(this); +// outExe = new QProcess(this); // outExe->start(SettingConfig::getInstance().OUT_EXE_FILE); ui->setupUi(this); @@ -31,6 +31,7 @@ initFaceRecogThread(); // 人脸识别线程 initIrisRegistThread(); // 虹膜注册线程 initIrisRecogThread(); // 虹膜识别线程 + initCameraPositionThread(); // 调整相机位置 // 初始化人脸相机控制 ProMemory::getInstance().faceCam = new FaceCameraController(this); @@ -49,6 +50,12 @@ connect(ProMemory::getInstance().irisCam->rightHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, addPersonForm, &AddPersonForm::drawIrisImageOnFrame); + // 初始化电机控制 + ProMemory::getInstance().moto = new MotoController(this); + ProMemory::getInstance().moto->initSerialMCU(); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::motoControl, + ProMemory::getInstance().moto, &MotoController::autoPosition); + // 打印日志 LOG(INFO) << QString("应用程序启动成功[Application Startup Success]").toStdString(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::MAIN_PAGE; @@ -72,6 +79,10 @@ ProMemory::getInstance().irisRecogPro->deleteLater(); ProMemory::getInstance().irisRecogPro->wait(); + ProMemory::getInstance().camPosCtrl->exitThread(); + ProMemory::getInstance().camPosCtrl->deleteLater(); + ProMemory::getInstance().camPosCtrl->wait(); + // 关闭自动启动的外部程序 // outExe->close(); // delete outExe; @@ -81,12 +92,14 @@ delete ProMemory::getInstance().faceRecogPro; delete ProMemory::getInstance().irisRegistPro; delete ProMemory::getInstance().irisRecogPro; + delete ProMemory::getInstance().camPosCtrl; } void CasicBioRecWin::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: + LOG(INFO) << "" << std::endl; QTimer::singleShot(100, qApp, SLOT(quit())); default: @@ -204,8 +217,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -244,8 +255,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -255,3 +264,17 @@ ProMemory::getInstance().irisRecogPro->start(); } + +void CasicBioRecWin::initCameraPositionThread() +{ + // 调整相机位置处理 + ProMemory::getInstance().camPosCtrl = new CameraPositionController(this); + + // 绑定信号与槽函数 + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTips, + recogResultForm, &RecognizeResultForm::updateRecogTips); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTipsBackgroundColor, + recogResultForm, &RecognizeResultForm::updateRecogTipsColor); + + ProMemory::getInstance().camPosCtrl->start(); +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h index b70245a..b5a3db9 100644 --- a/CasicBioRecWin.h +++ b/CasicBioRecWin.h @@ -54,6 +54,7 @@ void initFaceRecogThread(); void initIrisRegistThread(); void initIrisRecogThread(); + void initCameraPositionThread(); }; #endif // CASICBIORECWIN_H diff --git a/RecognizeResultForm.cpp b/RecognizeResultForm.cpp index e45a191..b340be9 100644 --- a/RecognizeResultForm.cpp +++ b/RecognizeResultForm.cpp @@ -20,7 +20,7 @@ RecognizeResultForm::~RecognizeResultForm() { - delete ui; + delete ui; } void RecognizeResultForm::startWorkingRecognize() @@ -29,23 +29,32 @@ switch (SettingConfig::getInstance().RECOG_TYPE) { case 1: // 人脸识别 + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); break; case 2: // 虹膜识别 + ProMemory::getInstance().clearIrisQueue(); +// ProMemory::getInstance().camPosCtrl->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; case 3: + // 双认证 先打开人脸识别 成功后再进行虹膜识别 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(true); + break; case 4: // 人脸和虹膜都需要打开 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; } - // 将界面切换到识别界面 RecognizeResultForm + // 开始拍图并显示视频 ProMemory::getInstance().faceCam->openFaceCamera(SettingConfig::getInstance().FACE_FRAME_INTERVAL); ui->labBackground->raise(); @@ -80,6 +89,14 @@ ui->widgetFail->raise(); ui->widgetFail->show(); + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().camPosCtrl->setWorking(false); + + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(false); + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ ui->labBackground->raise(); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -137,9 +154,9 @@ case 1: { // 仅人脸识别 - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); LOG(DEBUG) << QString("[RecognizeResultForm] 人脸识别成功 [%1]").arg(CasicFaceRecState::getInstance().toString()).toStdString(); @@ -158,9 +175,12 @@ case 2: { // 仅虹膜识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + // 停止控制电机和提示 + ProMemory::getInstance().camPosCtrl->setWorking(false); LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜识别成功 [%1]").arg(CasicIrisRecState::getInstance().toString()).toStdString(); @@ -179,13 +199,13 @@ case 4: { // 任意识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); QString logStr = QString("[RecognizeResultForm]%1识别成功[%2]"); if (faceOrIris == 1) @@ -213,42 +233,56 @@ if (faceOrIris == 1) { this->personIdByFace = personId; + + // 人脸识别成功后 开始进行虹膜识别 + // 1. 首先停止人脸识别 + ProMemory::getInstance().faceRecogPro->setWorking(false); + ProMemory::getInstance().clearFaceQueue(); + + // 2. 虹膜识别开始 + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().camPosCtrl->setWorking(true); } else if (faceOrIris == 2) { this->personIdByIris = personId; + + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) + { + // 只有一个成功的结果 需要等待下次 + return; + } else if (personIdByFace != personIdByIris) + { + // 人脸和虹膜识别的不是同一人 识别失败 + LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); + SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); + showRecogFailure(); + } else + { + LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); + showRecognizeResult(personId); + + // 识别记录存入数据库 + RecognitionRecordDao recDao; + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("type", "3"); + record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); + recDao.save(record); + } } - - if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) - { - // 只有一个成功的结果 需要等待下次 - return; - } else if (personIdByFace != personIdByIris) - { - // 人脸和虹膜识别的不是同一人 识别失败 - LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); - SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); - showRecogFailure(); - } else - { - LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); - showRecognizeResult(personId); - } - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - ProMemory::getInstance().clearFaceQueue(); - ProMemory::getInstance().faceRecogPro->setWorking(false); - ProMemory::getInstance().faceCam->stopTakingPhoto(); - - // 识别记录存入数据库 - RecognitionRecordDao recDao; - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("type", "4"); - record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); - recDao.save(record); } } + +void RecognizeResultForm::updateRecogTips(QString tipsText) +{ + ui->labTitle->setText(tipsText); +} +void RecognizeResultForm::updateRecogTipsColor(QString bgColor) +{ + ui->labTitle->setStyleSheet("background: " + bgColor); +} diff --git a/RecognizeResultForm.h b/RecognizeResultForm.h index 2c51865..65dd8ad 100644 --- a/RecognizeResultForm.h +++ b/RecognizeResultForm.h @@ -30,6 +30,8 @@ void startWorkingRecognize(); // 开始工作 void drawImageOnHomeForm(QImage imageDisp); + void updateRecogTips(QString tipsText); + void updateRecogTipsColor(QString bgColor); private: Ui::RecognizeResultForm *ui; diff --git a/StartupForm.cpp b/StartupForm.cpp index 16c4dfc..cf20de1 100644 --- a/StartupForm.cpp +++ b/StartupForm.cpp @@ -20,17 +20,23 @@ } // 设置弹簧的高度和宽度 - ui->vsTop->changeSize(0, 200); - ui->vsMidd->changeSize(0, 100); ui->hsLeft->changeSize(400, 0); ui->hsMidd->changeSize(150, 0); + // 绑定时间和日期的标签单击事件 单击即开始识别 + connect(ui->labDate, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + connect(ui->labTime, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + // 初始化更新界面的定时器 // 每秒执行一次 connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &StartupForm::updateDateAndTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, - this, &StartupForm::takeOneFrameForCheckStatus); +// connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, +// this, &StartupForm::takeOneFrameForCheckStatus); TimeCounterUtil::getInstance().clockCounter->start(1000); } diff --git a/StartupForm.h b/StartupForm.h index f2850e9..fc79be0 100644 --- a/StartupForm.h +++ b/StartupForm.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "casic/ProMemory.h" #include "utils/UtilInclude.h" diff --git a/StartupForm.ui b/StartupForm.ui index afb610f..de353f3 100644 --- a/StartupForm.ui +++ b/StartupForm.ui @@ -15,20 +15,7 @@ - - - Qt::Vertical - - - - 17 - 166 - - - - - - + TextLabel @@ -38,7 +25,7 @@ - + TextLabel @@ -48,19 +35,6 @@ - - - Qt::Vertical - - - - 17 - 167 - - - - - @@ -158,6 +132,13 @@ + + + QDblClickLabel + QLabel +
QDblClickLabel.h
+
+
diff --git a/casic/ProMemory.h b/casic/ProMemory.h index 3e9fbd4..02a14cf 100644 --- a/casic/ProMemory.h +++ b/casic/ProMemory.h @@ -16,6 +16,8 @@ #include "device/face/FaceRecogProcess.h" #include "device/iris/IrisRegistProcess.h" #include "device/iris/IrisRecogProcess.h" +#include "device/MotoController.h" +#include "device/CameraPositionController.h" class FaceCameraController; class IrisCameraController; @@ -23,6 +25,8 @@ class FaceRecogProcess; class IrisRegistProcess; class IrisRecogProcess; +class MotoController; +class CameraPositionController; class ProMemory { @@ -66,6 +70,10 @@ IrisRegistProcess * irisRegistPro; IrisRecogProcess * irisRecogPro; + MotoController * moto; + + CameraPositionController * camPosCtrl; + private: ProMemory(); diff --git a/casic/face/CasicFaceInterface.cpp b/casic/face/CasicFaceInterface.cpp index f530212..3cb2118 100644 --- a/casic/face/CasicFaceInterface.cpp +++ b/casic/face/CasicFaceInterface.cpp @@ -45,8 +45,6 @@ delete this->cascade; this->cascade = nullptr; } - - LOG(DEBUG) << "delete models in destructor"; } void casic::face::CasicFaceInterface::setDetectorModelPath(std::string detectorModelPath) @@ -384,6 +382,9 @@ cv::Size minRectSize(minFaceSize, minFaceSize); cv::Size maxRectSize(maxFaceSize, maxFaceSize); + QElapsedTimer timer; + timer.start(); + // ★分类器对象调用 cascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); @@ -391,6 +392,8 @@ { return cv::Rect(0, 0, 0, 0); } + + LOG(DEBUG) << QString("人脸分类检测算法[tm: %1 ms][%2, %3]").arg(timer.elapsed()).arg(rect.at(0).width).arg(rect.at(0).height).toStdString(); return rect.at(0); } @@ -424,7 +427,7 @@ return rect.at(0); } -bool casic::face::CasicFaceInterface::hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize) +std::vector casic::face::CasicFaceInterface::eyeDetectByCVCascade(cv::Mat frame, int minEyeSize) { // 构建openCV自带的眼睛分类器 if (this->eyeCascade == nullptr) @@ -433,14 +436,14 @@ this->eyeCascade->load(cvEyeCascadeName); } - std::vector rect; + std::vector rectVec; cv::Size minRectSize(minEyeSize, minEyeSize); cv::Size maxRectSize(maxEyeSize, maxEyeSize); // ★分类器对象调用 - eyeCascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); + eyeCascade->detectMultiScale(frame, rectVec, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); - return rect.size() == 0 ? false : true; + return rectVec; } void casic::face::CasicFaceInterface::setMinFaceSize(int minFaceSize) diff --git a/casic/face/CasicFaceInterface.h b/casic/face/CasicFaceInterface.h index 9d8b8ea..1753bd1 100644 --- a/casic/face/CasicFaceInterface.h +++ b/casic/face/CasicFaceInterface.h @@ -52,7 +52,7 @@ cv::Rect faceDetectByCVCascade(cv::Mat frame, int minFaceSize); cv::Rect eyeDetectByCVCascade(cv::Mat frame); - bool hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize); + std::vector eyeDetectByCVCascade(cv::Mat frame, int minEyeSize); void setMinFaceSize(int minFaceSize); void setMinEyeSize(int minEyeSize); private: diff --git a/dao/RecognitionRecordDao.cpp b/dao/RecognitionRecordDao.cpp index 403894a..d7103f9 100644 --- a/dao/RecognitionRecordDao.cpp +++ b/dao/RecognitionRecordDao.cpp @@ -91,13 +91,14 @@ .arg(object.value("type").toString()) .arg(object.value("dev_code").toString()) .arg(object.value("door_code").toString()) - .arg(object.value("inout_type").toString()); + .arg(object.value("inout_type").toString()) + .arg(object.value("debug_info").toString()); query.prepare(sql); LOG(DEBUG) << sql.toStdString(); // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES ('%1', '%2')") + QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES ('%1', '%2')") .arg(id).arg(object.value("debug_info").toString()); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/device/CameraPositionController.cpp b/device/CameraPositionController.cpp new file mode 100644 index 0000000..577c9ad --- /dev/null +++ b/device/CameraPositionController.cpp @@ -0,0 +1,91 @@ +#include "CameraPositionController.h" + +CameraPositionController::CameraPositionController(QObject *parent) : QThread(parent) +{ + this->working = false; + this->exit = false; +} + +CameraPositionController::~CameraPositionController() +{ + this->setWorking(false); +} + +void CameraPositionController::setWorking(bool working) +{ + this->working = working; +} +void CameraPositionController::exitThread() +{ + this->working = false; + this->exit = true; +} + +void CameraPositionController::run() +{ + while (exit == false) + { + if (this->working == false) + { + this->msleep(200); // 200ms后再判断 + continue; + } + + // 取一幅图像 + cv::Mat rawFrame = ProMemory::getInstance().faceCam->takeOneRawFrame(); +/* + // 分类器找眼睛 + cv::Rect eyeRect = casic::face::CasicFaceInterface::getInstance().eyeDetectByCVCascade(rawFrame); + if (eyeRect.width != 0) + { + // 眼睛的位置 + int eyeCenter = eyeRect.y + eyeRect.height / 2; + LOG(DEBUG) << eyeCenter << " " << abs(eyeCenter - 300) << " " << 100 * abs(eyeCenter - 300) / 20 + 200; + + if (eyeCenter < 250 || eyeCenter > 350) + { +// ProMemory::getInstance().moto->autoPosition(eyeCenter); + emit motoControl(eyeCenter); + +// this->msleep(100 * abs(eyeCenter - 300) / 20 + 200); // 200ms后再判断 + } + } + */ + + // 分类器找脸 + cv::Rect faceRect = casic::face::CasicFaceInterface::getInstance().faceDetectByCVCascade(rawFrame, SettingConfig::getInstance().MIN_WORK_FACE_SIZE); + QString facePos = QString("%1 * %2, (%3, %4), (%5, %6)").arg(faceRect.width).arg(faceRect.height) + .arg(faceRect.x).arg(faceRect.y).arg(faceRect.x + faceRect.width).arg(faceRect.y + faceRect.height); + + if (faceRect.width != 0) + { + // 通过人脸的大小判断距离,提示靠近或者远离 + if (faceRect.width < 360) + { + emit updateTips(QString("距离太远,请靠近 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#9F1919"); + } else if (faceRect.width >= 360 && faceRect.width <= 480) + { + emit updateTips(QString("正在识别,请保持 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#248A53"); + + // 位置合适 开始识别 +// ProMemory::getInstance().irisRecogPro->setWorking(true); +// ProMemory::getInstance().irisCam->startCapture(); +// this->setWorking(false); + } else if (faceRect.width > 480) + { + emit updateTips(QString("距离太近,请远离 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#9F1919"); + } + } + + this->msleep(500); + } +} + + +void CameraPositionController::checkFacePosition() +{ + +} diff --git a/device/CameraPositionController.h b/device/CameraPositionController.h new file mode 100644 index 0000000..9520b14 --- /dev/null +++ b/device/CameraPositionController.h @@ -0,0 +1,39 @@ +#ifndef CAMERAPOSITIONCONTROLLER_H +#define CAMERAPOSITIONCONTROLLER_H + +#include +#include + +#include "opencv2/opencv.hpp" +#include "utils/UtilInclude.h" +#include "casic/ProMemory.h" + +class CameraPositionController : public QThread +{ + Q_OBJECT +public: + explicit CameraPositionController(QObject *parent = 0); + ~CameraPositionController(); + + void setWorking(bool working); + void exitThread(); + +protected: + //QThread的虚函数 + //线程处理函数 + //不能直接调用, 通过start()间接调用 + void run(); + + volatile bool working; + volatile bool exit; + +public slots: + void checkFacePosition(); + +signals: + void updateTips(QString tipsText); + void updateTipsBackgroundColor(QString bgColor); + void motoControl(int eyeCenter); +}; + +#endif // CAMERAPOSITIONCONTROLLER_H diff --git a/device/FaceCameraController.cpp b/device/FaceCameraController.cpp index 0fe4b4c..2a4d7cb 100644 --- a/device/FaceCameraController.cpp +++ b/device/FaceCameraController.cpp @@ -41,8 +41,7 @@ void FaceCameraController::closeFaceCamera() { faceCap->release(); - - delete faceCap; +// delete faceCap; } @@ -88,7 +87,7 @@ // 拍图 faceCap->read(faceMat); - LOG(TRACE) << "TAKE ONE FACE FRAME " << faceMat.cols << " * " << faceMat.rows; + LOG(TRACE) << QThread::currentThreadId() << " TAKE ONE FACE FRAME " << faceMat.cols << " * " << faceMat.rows; // 左右翻转 cv::Mat imageMatMiir; diff --git a/device/MotoController.cpp b/device/MotoController.cpp new file mode 100644 index 0000000..15cb5f0 --- /dev/null +++ b/device/MotoController.cpp @@ -0,0 +1,127 @@ +#include "MotoController.h" + + +MotoController::MotoController(QObject *parent) : QObject(parent) +{ + this->portName = "COM2"; + this->baudRate = "9600"; +} + + +bool MotoController::initSerialMCU() +{ + QList list = QSerialPortInfo::availablePorts(); + if (list.isEmpty() == true) + return false; + + this->portName = SettingConfig::getInstance().PORT_NAME; + + serial.setPortName(this->portName); + serial.setBaudRate(this->baudRate.toInt()); + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); + + bool succ = serial.open(QIODevice::ReadWrite); + + //连接信号和槽 + + LOG(DEBUG) << QString("[MotoController][initSerialMCU]打开电机串口[%1][%2][%3]").arg(portName).arg(baudRate).arg(succ).toStdString(); + + return succ; +} + +void MotoController::sendDataAutoEnding(QByteArray data) +{ + LOG(INFO) << QString("向串口发送数据[send] %1").arg(data.data()).toStdString(); + + // 加上0x0D 0x0A换行结束 + data.append(0x0D).append(0x0A); + serial.write(data); +} + + +/** + * @brief MotoController::encodeProtocol + * @param content + * @return + * 格式 +0000 00 长度=9 + * bit1 = +/- +表示向上运动 -表示向下运动 + * bit2-bit4 表示调整的量 + * bit5 开关灯控制量 + * bit6 空格 + * bit7-bit8 数值的累加和 + * bit9 空格 + */ +QByteArray MotoController::encodeProtocol(QString content) +{ + if (content.toInt() > 0) + { + content = "+" + content; + } + + // 调整数值的绝对值 三位数字 + int abs = content.mid(1, content.length()).toInt(); + + // 补齐3位数值 + if (abs < 10) + { + content.insert(1, "00"); + } else if (abs < 100) + { + content.insert(1, "0"); + } + + // 计算累加和 + int sum = 0; + for (int i = 0; i < content.mid(1, content.length()).length(); i++) + { + sum += content.mid(i + 1, 1).toInt(); + } + + // 格式化累加和字符串 + QString sumStr = QString::number(sum); + if (sumStr.length() == 1) + { + sumStr.prepend("0"); + } else if (sumStr.length() > 2) + { + sumStr = QString::number(sum).mid(0, 2); + } + + // 开关灯的控制量 = 0 + content.append("0"); + content = content.append(0x20).append(sumStr).append(0x20); + + return content.toUtf8(); +} + +void MotoController::autoFacePosition(CasicFaceInfo * faceInfo) +{ + if (faceInfo->hasFace == false) + { + return; + } + + const int centerLine = 300; + int faceTop = faceInfo->faceRecTL[1]; + int faceCenterLine = faceTop + faceInfo->face.pos.height / 2; + + int diff = (faceCenterLine - centerLine) * -0.8; + QByteArray data = this->encodeProtocol(QString::number(diff)); + this->sendDataAutoEnding(data); +} + +void MotoController::autoPosition(int eyeCenter) +{ + int center = 300; + int dir = eyeCenter > center ? -1 : 1; + int step = abs(eyeCenter - center) / 20; + for (int i = 0; i < step; i++) + { + QByteArray data = this->encodeProtocol(QString::number(20 * dir)); + this->sendDataAutoEnding(data); + QThread::msleep(100); + } +} diff --git a/device/MotoController.h b/device/MotoController.h new file mode 100644 index 0000000..60aa5dc --- /dev/null +++ b/device/MotoController.h @@ -0,0 +1,39 @@ +#ifndef MOTOCONTROLLER_H +#define MOTOCONTROLLER_H + +#include +#include +#include +#include + +#include "casic/face/CasicFaceInfo.h" +#include "utils/UtilInclude.h" + +class MotoController : public QObject +{ + Q_OBJECT +public: + explicit MotoController(QObject *parent = nullptr); + + // 打开串口 + bool initSerialMCU(); + +public slots: + void autoFacePosition(CasicFaceInfo * faceInfo); + void autoPosition(int eyeCenter); + +private: + QSerialPort serial; + QString portName; + QString baudRate; + + QByteArray buffRecv; + + QByteArray encodeProtocol(QString content); + void sendDataAutoEnding(QByteArray data); + +signals: + +}; + +#endif // MOTOCONTROLLER_H diff --git a/device/device.pri b/device/device.pri index 64e6e17..2a1b90b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,10 +1,12 @@ -HEADERS += $$PWD/FaceCameraController.h +HEADERS += $$PWD/FaceCameraController.h \ + $$PWD/CameraPositionController.h HEADERS += $$PWD/face/FaceRecogProcess.h HEADERS += $$PWD/face/FaceRegistProcess.h HEADERS += $$PWD/face/CasicFaceRecState.h -SOURCES += $$PWD/FaceCameraController.cpp +SOURCES += $$PWD/FaceCameraController.cpp \ + $$PWD/CameraPositionController.cpp SOURCES += $$PWD/face/FaceRecogProcess.cpp SOURCES += $$PWD/face/FaceRegistProcess.cpp SOURCES += $$PWD/face/CasicFaceRecState.cpp @@ -14,11 +16,14 @@ HEADERS += $$PWD/iris/IrisRegistProcess.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h -#HEADERS += $$PWD/MotoController.h SOURCES += $$PWD/IrisCameraController.cpp SOURCES += $$PWD/IrisCameraCapEventHandler.cpp SOURCES += $$PWD/iris/IrisRegistProcess.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp -#SOURCES += $$PWD/MotoController.cpp + +HEADERS += $$PWD/MotoController.h +SOURCES += $$PWD/MotoController.cpp +HEADERS += +SOURCES += diff --git a/qss/startup.css b/qss/startup.css index 9c9b4d6..77027e8 100644 --- a/qss/startup.css +++ b/qss/startup.css @@ -4,11 +4,13 @@ } QLabel#labDate { - font-size: 36px; + font-size: 48px; + padding-bottom: 100px; } QLabel#labTime { font-size: 100px; + padding-top: 200px; } QToolButton { diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp index f202cfe..bc8018b 100644 --- a/CasicBioRecWin.cpp +++ b/CasicBioRecWin.cpp @@ -6,7 +6,7 @@ , ui(new Ui::CasicBioRecWin) { // 打开外部可执行程序 - outExe = new QProcess(this); +// outExe = new QProcess(this); // outExe->start(SettingConfig::getInstance().OUT_EXE_FILE); ui->setupUi(this); @@ -31,6 +31,7 @@ initFaceRecogThread(); // 人脸识别线程 initIrisRegistThread(); // 虹膜注册线程 initIrisRecogThread(); // 虹膜识别线程 + initCameraPositionThread(); // 调整相机位置 // 初始化人脸相机控制 ProMemory::getInstance().faceCam = new FaceCameraController(this); @@ -49,6 +50,12 @@ connect(ProMemory::getInstance().irisCam->rightHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, addPersonForm, &AddPersonForm::drawIrisImageOnFrame); + // 初始化电机控制 + ProMemory::getInstance().moto = new MotoController(this); + ProMemory::getInstance().moto->initSerialMCU(); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::motoControl, + ProMemory::getInstance().moto, &MotoController::autoPosition); + // 打印日志 LOG(INFO) << QString("应用程序启动成功[Application Startup Success]").toStdString(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::MAIN_PAGE; @@ -72,6 +79,10 @@ ProMemory::getInstance().irisRecogPro->deleteLater(); ProMemory::getInstance().irisRecogPro->wait(); + ProMemory::getInstance().camPosCtrl->exitThread(); + ProMemory::getInstance().camPosCtrl->deleteLater(); + ProMemory::getInstance().camPosCtrl->wait(); + // 关闭自动启动的外部程序 // outExe->close(); // delete outExe; @@ -81,12 +92,14 @@ delete ProMemory::getInstance().faceRecogPro; delete ProMemory::getInstance().irisRegistPro; delete ProMemory::getInstance().irisRecogPro; + delete ProMemory::getInstance().camPosCtrl; } void CasicBioRecWin::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: + LOG(INFO) << "" << std::endl; QTimer::singleShot(100, qApp, SLOT(quit())); default: @@ -204,8 +217,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -244,8 +255,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -255,3 +264,17 @@ ProMemory::getInstance().irisRecogPro->start(); } + +void CasicBioRecWin::initCameraPositionThread() +{ + // 调整相机位置处理 + ProMemory::getInstance().camPosCtrl = new CameraPositionController(this); + + // 绑定信号与槽函数 + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTips, + recogResultForm, &RecognizeResultForm::updateRecogTips); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTipsBackgroundColor, + recogResultForm, &RecognizeResultForm::updateRecogTipsColor); + + ProMemory::getInstance().camPosCtrl->start(); +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h index b70245a..b5a3db9 100644 --- a/CasicBioRecWin.h +++ b/CasicBioRecWin.h @@ -54,6 +54,7 @@ void initFaceRecogThread(); void initIrisRegistThread(); void initIrisRecogThread(); + void initCameraPositionThread(); }; #endif // CASICBIORECWIN_H diff --git a/RecognizeResultForm.cpp b/RecognizeResultForm.cpp index e45a191..b340be9 100644 --- a/RecognizeResultForm.cpp +++ b/RecognizeResultForm.cpp @@ -20,7 +20,7 @@ RecognizeResultForm::~RecognizeResultForm() { - delete ui; + delete ui; } void RecognizeResultForm::startWorkingRecognize() @@ -29,23 +29,32 @@ switch (SettingConfig::getInstance().RECOG_TYPE) { case 1: // 人脸识别 + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); break; case 2: // 虹膜识别 + ProMemory::getInstance().clearIrisQueue(); +// ProMemory::getInstance().camPosCtrl->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; case 3: + // 双认证 先打开人脸识别 成功后再进行虹膜识别 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(true); + break; case 4: // 人脸和虹膜都需要打开 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; } - // 将界面切换到识别界面 RecognizeResultForm + // 开始拍图并显示视频 ProMemory::getInstance().faceCam->openFaceCamera(SettingConfig::getInstance().FACE_FRAME_INTERVAL); ui->labBackground->raise(); @@ -80,6 +89,14 @@ ui->widgetFail->raise(); ui->widgetFail->show(); + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().camPosCtrl->setWorking(false); + + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(false); + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ ui->labBackground->raise(); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -137,9 +154,9 @@ case 1: { // 仅人脸识别 - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); LOG(DEBUG) << QString("[RecognizeResultForm] 人脸识别成功 [%1]").arg(CasicFaceRecState::getInstance().toString()).toStdString(); @@ -158,9 +175,12 @@ case 2: { // 仅虹膜识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + // 停止控制电机和提示 + ProMemory::getInstance().camPosCtrl->setWorking(false); LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜识别成功 [%1]").arg(CasicIrisRecState::getInstance().toString()).toStdString(); @@ -179,13 +199,13 @@ case 4: { // 任意识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); QString logStr = QString("[RecognizeResultForm]%1识别成功[%2]"); if (faceOrIris == 1) @@ -213,42 +233,56 @@ if (faceOrIris == 1) { this->personIdByFace = personId; + + // 人脸识别成功后 开始进行虹膜识别 + // 1. 首先停止人脸识别 + ProMemory::getInstance().faceRecogPro->setWorking(false); + ProMemory::getInstance().clearFaceQueue(); + + // 2. 虹膜识别开始 + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().camPosCtrl->setWorking(true); } else if (faceOrIris == 2) { this->personIdByIris = personId; + + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) + { + // 只有一个成功的结果 需要等待下次 + return; + } else if (personIdByFace != personIdByIris) + { + // 人脸和虹膜识别的不是同一人 识别失败 + LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); + SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); + showRecogFailure(); + } else + { + LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); + showRecognizeResult(personId); + + // 识别记录存入数据库 + RecognitionRecordDao recDao; + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("type", "3"); + record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); + recDao.save(record); + } } - - if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) - { - // 只有一个成功的结果 需要等待下次 - return; - } else if (personIdByFace != personIdByIris) - { - // 人脸和虹膜识别的不是同一人 识别失败 - LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); - SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); - showRecogFailure(); - } else - { - LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); - showRecognizeResult(personId); - } - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - ProMemory::getInstance().clearFaceQueue(); - ProMemory::getInstance().faceRecogPro->setWorking(false); - ProMemory::getInstance().faceCam->stopTakingPhoto(); - - // 识别记录存入数据库 - RecognitionRecordDao recDao; - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("type", "4"); - record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); - recDao.save(record); } } + +void RecognizeResultForm::updateRecogTips(QString tipsText) +{ + ui->labTitle->setText(tipsText); +} +void RecognizeResultForm::updateRecogTipsColor(QString bgColor) +{ + ui->labTitle->setStyleSheet("background: " + bgColor); +} diff --git a/RecognizeResultForm.h b/RecognizeResultForm.h index 2c51865..65dd8ad 100644 --- a/RecognizeResultForm.h +++ b/RecognizeResultForm.h @@ -30,6 +30,8 @@ void startWorkingRecognize(); // 开始工作 void drawImageOnHomeForm(QImage imageDisp); + void updateRecogTips(QString tipsText); + void updateRecogTipsColor(QString bgColor); private: Ui::RecognizeResultForm *ui; diff --git a/StartupForm.cpp b/StartupForm.cpp index 16c4dfc..cf20de1 100644 --- a/StartupForm.cpp +++ b/StartupForm.cpp @@ -20,17 +20,23 @@ } // 设置弹簧的高度和宽度 - ui->vsTop->changeSize(0, 200); - ui->vsMidd->changeSize(0, 100); ui->hsLeft->changeSize(400, 0); ui->hsMidd->changeSize(150, 0); + // 绑定时间和日期的标签单击事件 单击即开始识别 + connect(ui->labDate, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + connect(ui->labTime, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + // 初始化更新界面的定时器 // 每秒执行一次 connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &StartupForm::updateDateAndTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, - this, &StartupForm::takeOneFrameForCheckStatus); +// connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, +// this, &StartupForm::takeOneFrameForCheckStatus); TimeCounterUtil::getInstance().clockCounter->start(1000); } diff --git a/StartupForm.h b/StartupForm.h index f2850e9..fc79be0 100644 --- a/StartupForm.h +++ b/StartupForm.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "casic/ProMemory.h" #include "utils/UtilInclude.h" diff --git a/StartupForm.ui b/StartupForm.ui index afb610f..de353f3 100644 --- a/StartupForm.ui +++ b/StartupForm.ui @@ -15,20 +15,7 @@ - - - Qt::Vertical - - - - 17 - 166 - - - - - - + TextLabel @@ -38,7 +25,7 @@ - + TextLabel @@ -48,19 +35,6 @@ - - - Qt::Vertical - - - - 17 - 167 - - - - - @@ -158,6 +132,13 @@ + + + QDblClickLabel + QLabel +
QDblClickLabel.h
+
+
diff --git a/casic/ProMemory.h b/casic/ProMemory.h index 3e9fbd4..02a14cf 100644 --- a/casic/ProMemory.h +++ b/casic/ProMemory.h @@ -16,6 +16,8 @@ #include "device/face/FaceRecogProcess.h" #include "device/iris/IrisRegistProcess.h" #include "device/iris/IrisRecogProcess.h" +#include "device/MotoController.h" +#include "device/CameraPositionController.h" class FaceCameraController; class IrisCameraController; @@ -23,6 +25,8 @@ class FaceRecogProcess; class IrisRegistProcess; class IrisRecogProcess; +class MotoController; +class CameraPositionController; class ProMemory { @@ -66,6 +70,10 @@ IrisRegistProcess * irisRegistPro; IrisRecogProcess * irisRecogPro; + MotoController * moto; + + CameraPositionController * camPosCtrl; + private: ProMemory(); diff --git a/casic/face/CasicFaceInterface.cpp b/casic/face/CasicFaceInterface.cpp index f530212..3cb2118 100644 --- a/casic/face/CasicFaceInterface.cpp +++ b/casic/face/CasicFaceInterface.cpp @@ -45,8 +45,6 @@ delete this->cascade; this->cascade = nullptr; } - - LOG(DEBUG) << "delete models in destructor"; } void casic::face::CasicFaceInterface::setDetectorModelPath(std::string detectorModelPath) @@ -384,6 +382,9 @@ cv::Size minRectSize(minFaceSize, minFaceSize); cv::Size maxRectSize(maxFaceSize, maxFaceSize); + QElapsedTimer timer; + timer.start(); + // ★分类器对象调用 cascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); @@ -391,6 +392,8 @@ { return cv::Rect(0, 0, 0, 0); } + + LOG(DEBUG) << QString("人脸分类检测算法[tm: %1 ms][%2, %3]").arg(timer.elapsed()).arg(rect.at(0).width).arg(rect.at(0).height).toStdString(); return rect.at(0); } @@ -424,7 +427,7 @@ return rect.at(0); } -bool casic::face::CasicFaceInterface::hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize) +std::vector casic::face::CasicFaceInterface::eyeDetectByCVCascade(cv::Mat frame, int minEyeSize) { // 构建openCV自带的眼睛分类器 if (this->eyeCascade == nullptr) @@ -433,14 +436,14 @@ this->eyeCascade->load(cvEyeCascadeName); } - std::vector rect; + std::vector rectVec; cv::Size minRectSize(minEyeSize, minEyeSize); cv::Size maxRectSize(maxEyeSize, maxEyeSize); // ★分类器对象调用 - eyeCascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); + eyeCascade->detectMultiScale(frame, rectVec, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); - return rect.size() == 0 ? false : true; + return rectVec; } void casic::face::CasicFaceInterface::setMinFaceSize(int minFaceSize) diff --git a/casic/face/CasicFaceInterface.h b/casic/face/CasicFaceInterface.h index 9d8b8ea..1753bd1 100644 --- a/casic/face/CasicFaceInterface.h +++ b/casic/face/CasicFaceInterface.h @@ -52,7 +52,7 @@ cv::Rect faceDetectByCVCascade(cv::Mat frame, int minFaceSize); cv::Rect eyeDetectByCVCascade(cv::Mat frame); - bool hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize); + std::vector eyeDetectByCVCascade(cv::Mat frame, int minEyeSize); void setMinFaceSize(int minFaceSize); void setMinEyeSize(int minEyeSize); private: diff --git a/dao/RecognitionRecordDao.cpp b/dao/RecognitionRecordDao.cpp index 403894a..d7103f9 100644 --- a/dao/RecognitionRecordDao.cpp +++ b/dao/RecognitionRecordDao.cpp @@ -91,13 +91,14 @@ .arg(object.value("type").toString()) .arg(object.value("dev_code").toString()) .arg(object.value("door_code").toString()) - .arg(object.value("inout_type").toString()); + .arg(object.value("inout_type").toString()) + .arg(object.value("debug_info").toString()); query.prepare(sql); LOG(DEBUG) << sql.toStdString(); // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES ('%1', '%2')") + QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES ('%1', '%2')") .arg(id).arg(object.value("debug_info").toString()); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/device/CameraPositionController.cpp b/device/CameraPositionController.cpp new file mode 100644 index 0000000..577c9ad --- /dev/null +++ b/device/CameraPositionController.cpp @@ -0,0 +1,91 @@ +#include "CameraPositionController.h" + +CameraPositionController::CameraPositionController(QObject *parent) : QThread(parent) +{ + this->working = false; + this->exit = false; +} + +CameraPositionController::~CameraPositionController() +{ + this->setWorking(false); +} + +void CameraPositionController::setWorking(bool working) +{ + this->working = working; +} +void CameraPositionController::exitThread() +{ + this->working = false; + this->exit = true; +} + +void CameraPositionController::run() +{ + while (exit == false) + { + if (this->working == false) + { + this->msleep(200); // 200ms后再判断 + continue; + } + + // 取一幅图像 + cv::Mat rawFrame = ProMemory::getInstance().faceCam->takeOneRawFrame(); +/* + // 分类器找眼睛 + cv::Rect eyeRect = casic::face::CasicFaceInterface::getInstance().eyeDetectByCVCascade(rawFrame); + if (eyeRect.width != 0) + { + // 眼睛的位置 + int eyeCenter = eyeRect.y + eyeRect.height / 2; + LOG(DEBUG) << eyeCenter << " " << abs(eyeCenter - 300) << " " << 100 * abs(eyeCenter - 300) / 20 + 200; + + if (eyeCenter < 250 || eyeCenter > 350) + { +// ProMemory::getInstance().moto->autoPosition(eyeCenter); + emit motoControl(eyeCenter); + +// this->msleep(100 * abs(eyeCenter - 300) / 20 + 200); // 200ms后再判断 + } + } + */ + + // 分类器找脸 + cv::Rect faceRect = casic::face::CasicFaceInterface::getInstance().faceDetectByCVCascade(rawFrame, SettingConfig::getInstance().MIN_WORK_FACE_SIZE); + QString facePos = QString("%1 * %2, (%3, %4), (%5, %6)").arg(faceRect.width).arg(faceRect.height) + .arg(faceRect.x).arg(faceRect.y).arg(faceRect.x + faceRect.width).arg(faceRect.y + faceRect.height); + + if (faceRect.width != 0) + { + // 通过人脸的大小判断距离,提示靠近或者远离 + if (faceRect.width < 360) + { + emit updateTips(QString("距离太远,请靠近 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#9F1919"); + } else if (faceRect.width >= 360 && faceRect.width <= 480) + { + emit updateTips(QString("正在识别,请保持 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#248A53"); + + // 位置合适 开始识别 +// ProMemory::getInstance().irisRecogPro->setWorking(true); +// ProMemory::getInstance().irisCam->startCapture(); +// this->setWorking(false); + } else if (faceRect.width > 480) + { + emit updateTips(QString("距离太近,请远离 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#9F1919"); + } + } + + this->msleep(500); + } +} + + +void CameraPositionController::checkFacePosition() +{ + +} diff --git a/device/CameraPositionController.h b/device/CameraPositionController.h new file mode 100644 index 0000000..9520b14 --- /dev/null +++ b/device/CameraPositionController.h @@ -0,0 +1,39 @@ +#ifndef CAMERAPOSITIONCONTROLLER_H +#define CAMERAPOSITIONCONTROLLER_H + +#include +#include + +#include "opencv2/opencv.hpp" +#include "utils/UtilInclude.h" +#include "casic/ProMemory.h" + +class CameraPositionController : public QThread +{ + Q_OBJECT +public: + explicit CameraPositionController(QObject *parent = 0); + ~CameraPositionController(); + + void setWorking(bool working); + void exitThread(); + +protected: + //QThread的虚函数 + //线程处理函数 + //不能直接调用, 通过start()间接调用 + void run(); + + volatile bool working; + volatile bool exit; + +public slots: + void checkFacePosition(); + +signals: + void updateTips(QString tipsText); + void updateTipsBackgroundColor(QString bgColor); + void motoControl(int eyeCenter); +}; + +#endif // CAMERAPOSITIONCONTROLLER_H diff --git a/device/FaceCameraController.cpp b/device/FaceCameraController.cpp index 0fe4b4c..2a4d7cb 100644 --- a/device/FaceCameraController.cpp +++ b/device/FaceCameraController.cpp @@ -41,8 +41,7 @@ void FaceCameraController::closeFaceCamera() { faceCap->release(); - - delete faceCap; +// delete faceCap; } @@ -88,7 +87,7 @@ // 拍图 faceCap->read(faceMat); - LOG(TRACE) << "TAKE ONE FACE FRAME " << faceMat.cols << " * " << faceMat.rows; + LOG(TRACE) << QThread::currentThreadId() << " TAKE ONE FACE FRAME " << faceMat.cols << " * " << faceMat.rows; // 左右翻转 cv::Mat imageMatMiir; diff --git a/device/MotoController.cpp b/device/MotoController.cpp new file mode 100644 index 0000000..15cb5f0 --- /dev/null +++ b/device/MotoController.cpp @@ -0,0 +1,127 @@ +#include "MotoController.h" + + +MotoController::MotoController(QObject *parent) : QObject(parent) +{ + this->portName = "COM2"; + this->baudRate = "9600"; +} + + +bool MotoController::initSerialMCU() +{ + QList list = QSerialPortInfo::availablePorts(); + if (list.isEmpty() == true) + return false; + + this->portName = SettingConfig::getInstance().PORT_NAME; + + serial.setPortName(this->portName); + serial.setBaudRate(this->baudRate.toInt()); + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); + + bool succ = serial.open(QIODevice::ReadWrite); + + //连接信号和槽 + + LOG(DEBUG) << QString("[MotoController][initSerialMCU]打开电机串口[%1][%2][%3]").arg(portName).arg(baudRate).arg(succ).toStdString(); + + return succ; +} + +void MotoController::sendDataAutoEnding(QByteArray data) +{ + LOG(INFO) << QString("向串口发送数据[send] %1").arg(data.data()).toStdString(); + + // 加上0x0D 0x0A换行结束 + data.append(0x0D).append(0x0A); + serial.write(data); +} + + +/** + * @brief MotoController::encodeProtocol + * @param content + * @return + * 格式 +0000 00 长度=9 + * bit1 = +/- +表示向上运动 -表示向下运动 + * bit2-bit4 表示调整的量 + * bit5 开关灯控制量 + * bit6 空格 + * bit7-bit8 数值的累加和 + * bit9 空格 + */ +QByteArray MotoController::encodeProtocol(QString content) +{ + if (content.toInt() > 0) + { + content = "+" + content; + } + + // 调整数值的绝对值 三位数字 + int abs = content.mid(1, content.length()).toInt(); + + // 补齐3位数值 + if (abs < 10) + { + content.insert(1, "00"); + } else if (abs < 100) + { + content.insert(1, "0"); + } + + // 计算累加和 + int sum = 0; + for (int i = 0; i < content.mid(1, content.length()).length(); i++) + { + sum += content.mid(i + 1, 1).toInt(); + } + + // 格式化累加和字符串 + QString sumStr = QString::number(sum); + if (sumStr.length() == 1) + { + sumStr.prepend("0"); + } else if (sumStr.length() > 2) + { + sumStr = QString::number(sum).mid(0, 2); + } + + // 开关灯的控制量 = 0 + content.append("0"); + content = content.append(0x20).append(sumStr).append(0x20); + + return content.toUtf8(); +} + +void MotoController::autoFacePosition(CasicFaceInfo * faceInfo) +{ + if (faceInfo->hasFace == false) + { + return; + } + + const int centerLine = 300; + int faceTop = faceInfo->faceRecTL[1]; + int faceCenterLine = faceTop + faceInfo->face.pos.height / 2; + + int diff = (faceCenterLine - centerLine) * -0.8; + QByteArray data = this->encodeProtocol(QString::number(diff)); + this->sendDataAutoEnding(data); +} + +void MotoController::autoPosition(int eyeCenter) +{ + int center = 300; + int dir = eyeCenter > center ? -1 : 1; + int step = abs(eyeCenter - center) / 20; + for (int i = 0; i < step; i++) + { + QByteArray data = this->encodeProtocol(QString::number(20 * dir)); + this->sendDataAutoEnding(data); + QThread::msleep(100); + } +} diff --git a/device/MotoController.h b/device/MotoController.h new file mode 100644 index 0000000..60aa5dc --- /dev/null +++ b/device/MotoController.h @@ -0,0 +1,39 @@ +#ifndef MOTOCONTROLLER_H +#define MOTOCONTROLLER_H + +#include +#include +#include +#include + +#include "casic/face/CasicFaceInfo.h" +#include "utils/UtilInclude.h" + +class MotoController : public QObject +{ + Q_OBJECT +public: + explicit MotoController(QObject *parent = nullptr); + + // 打开串口 + bool initSerialMCU(); + +public slots: + void autoFacePosition(CasicFaceInfo * faceInfo); + void autoPosition(int eyeCenter); + +private: + QSerialPort serial; + QString portName; + QString baudRate; + + QByteArray buffRecv; + + QByteArray encodeProtocol(QString content); + void sendDataAutoEnding(QByteArray data); + +signals: + +}; + +#endif // MOTOCONTROLLER_H diff --git a/device/device.pri b/device/device.pri index 64e6e17..2a1b90b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,10 +1,12 @@ -HEADERS += $$PWD/FaceCameraController.h +HEADERS += $$PWD/FaceCameraController.h \ + $$PWD/CameraPositionController.h HEADERS += $$PWD/face/FaceRecogProcess.h HEADERS += $$PWD/face/FaceRegistProcess.h HEADERS += $$PWD/face/CasicFaceRecState.h -SOURCES += $$PWD/FaceCameraController.cpp +SOURCES += $$PWD/FaceCameraController.cpp \ + $$PWD/CameraPositionController.cpp SOURCES += $$PWD/face/FaceRecogProcess.cpp SOURCES += $$PWD/face/FaceRegistProcess.cpp SOURCES += $$PWD/face/CasicFaceRecState.cpp @@ -14,11 +16,14 @@ HEADERS += $$PWD/iris/IrisRegistProcess.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h -#HEADERS += $$PWD/MotoController.h SOURCES += $$PWD/IrisCameraController.cpp SOURCES += $$PWD/IrisCameraCapEventHandler.cpp SOURCES += $$PWD/iris/IrisRegistProcess.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp -#SOURCES += $$PWD/MotoController.cpp + +HEADERS += $$PWD/MotoController.h +SOURCES += $$PWD/MotoController.cpp +HEADERS += +SOURCES += diff --git a/qss/startup.css b/qss/startup.css index 9c9b4d6..77027e8 100644 --- a/qss/startup.css +++ b/qss/startup.css @@ -4,11 +4,13 @@ } QLabel#labDate { - font-size: 36px; + font-size: 48px; + padding-bottom: 100px; } QLabel#labTime { font-size: 100px; + padding-top: 200px; } QToolButton { diff --git a/utils/TimeCounterUtil.cpp b/utils/TimeCounterUtil.cpp index 275945f..e69de29 100644 --- a/utils/TimeCounterUtil.cpp +++ b/utils/TimeCounterUtil.cpp @@ -1,8 +0,0 @@ -#include "TimeCounterUtil.h" - -TimeCounterUtil::TimeCounterUtil() -{ - faceCapCounter = new QTimer(); - irisCapCounter = new QTimer(); - clockCounter = new QTimer(); -} diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp index f202cfe..bc8018b 100644 --- a/CasicBioRecWin.cpp +++ b/CasicBioRecWin.cpp @@ -6,7 +6,7 @@ , ui(new Ui::CasicBioRecWin) { // 打开外部可执行程序 - outExe = new QProcess(this); +// outExe = new QProcess(this); // outExe->start(SettingConfig::getInstance().OUT_EXE_FILE); ui->setupUi(this); @@ -31,6 +31,7 @@ initFaceRecogThread(); // 人脸识别线程 initIrisRegistThread(); // 虹膜注册线程 initIrisRecogThread(); // 虹膜识别线程 + initCameraPositionThread(); // 调整相机位置 // 初始化人脸相机控制 ProMemory::getInstance().faceCam = new FaceCameraController(this); @@ -49,6 +50,12 @@ connect(ProMemory::getInstance().irisCam->rightHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, addPersonForm, &AddPersonForm::drawIrisImageOnFrame); + // 初始化电机控制 + ProMemory::getInstance().moto = new MotoController(this); + ProMemory::getInstance().moto->initSerialMCU(); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::motoControl, + ProMemory::getInstance().moto, &MotoController::autoPosition); + // 打印日志 LOG(INFO) << QString("应用程序启动成功[Application Startup Success]").toStdString(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::MAIN_PAGE; @@ -72,6 +79,10 @@ ProMemory::getInstance().irisRecogPro->deleteLater(); ProMemory::getInstance().irisRecogPro->wait(); + ProMemory::getInstance().camPosCtrl->exitThread(); + ProMemory::getInstance().camPosCtrl->deleteLater(); + ProMemory::getInstance().camPosCtrl->wait(); + // 关闭自动启动的外部程序 // outExe->close(); // delete outExe; @@ -81,12 +92,14 @@ delete ProMemory::getInstance().faceRecogPro; delete ProMemory::getInstance().irisRegistPro; delete ProMemory::getInstance().irisRecogPro; + delete ProMemory::getInstance().camPosCtrl; } void CasicBioRecWin::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: + LOG(INFO) << "" << std::endl; QTimer::singleShot(100, qApp, SLOT(quit())); default: @@ -204,8 +217,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -244,8 +255,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -255,3 +264,17 @@ ProMemory::getInstance().irisRecogPro->start(); } + +void CasicBioRecWin::initCameraPositionThread() +{ + // 调整相机位置处理 + ProMemory::getInstance().camPosCtrl = new CameraPositionController(this); + + // 绑定信号与槽函数 + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTips, + recogResultForm, &RecognizeResultForm::updateRecogTips); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTipsBackgroundColor, + recogResultForm, &RecognizeResultForm::updateRecogTipsColor); + + ProMemory::getInstance().camPosCtrl->start(); +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h index b70245a..b5a3db9 100644 --- a/CasicBioRecWin.h +++ b/CasicBioRecWin.h @@ -54,6 +54,7 @@ void initFaceRecogThread(); void initIrisRegistThread(); void initIrisRecogThread(); + void initCameraPositionThread(); }; #endif // CASICBIORECWIN_H diff --git a/RecognizeResultForm.cpp b/RecognizeResultForm.cpp index e45a191..b340be9 100644 --- a/RecognizeResultForm.cpp +++ b/RecognizeResultForm.cpp @@ -20,7 +20,7 @@ RecognizeResultForm::~RecognizeResultForm() { - delete ui; + delete ui; } void RecognizeResultForm::startWorkingRecognize() @@ -29,23 +29,32 @@ switch (SettingConfig::getInstance().RECOG_TYPE) { case 1: // 人脸识别 + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); break; case 2: // 虹膜识别 + ProMemory::getInstance().clearIrisQueue(); +// ProMemory::getInstance().camPosCtrl->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; case 3: + // 双认证 先打开人脸识别 成功后再进行虹膜识别 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(true); + break; case 4: // 人脸和虹膜都需要打开 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; } - // 将界面切换到识别界面 RecognizeResultForm + // 开始拍图并显示视频 ProMemory::getInstance().faceCam->openFaceCamera(SettingConfig::getInstance().FACE_FRAME_INTERVAL); ui->labBackground->raise(); @@ -80,6 +89,14 @@ ui->widgetFail->raise(); ui->widgetFail->show(); + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().camPosCtrl->setWorking(false); + + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(false); + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ ui->labBackground->raise(); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -137,9 +154,9 @@ case 1: { // 仅人脸识别 - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); LOG(DEBUG) << QString("[RecognizeResultForm] 人脸识别成功 [%1]").arg(CasicFaceRecState::getInstance().toString()).toStdString(); @@ -158,9 +175,12 @@ case 2: { // 仅虹膜识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + // 停止控制电机和提示 + ProMemory::getInstance().camPosCtrl->setWorking(false); LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜识别成功 [%1]").arg(CasicIrisRecState::getInstance().toString()).toStdString(); @@ -179,13 +199,13 @@ case 4: { // 任意识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); QString logStr = QString("[RecognizeResultForm]%1识别成功[%2]"); if (faceOrIris == 1) @@ -213,42 +233,56 @@ if (faceOrIris == 1) { this->personIdByFace = personId; + + // 人脸识别成功后 开始进行虹膜识别 + // 1. 首先停止人脸识别 + ProMemory::getInstance().faceRecogPro->setWorking(false); + ProMemory::getInstance().clearFaceQueue(); + + // 2. 虹膜识别开始 + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().camPosCtrl->setWorking(true); } else if (faceOrIris == 2) { this->personIdByIris = personId; + + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) + { + // 只有一个成功的结果 需要等待下次 + return; + } else if (personIdByFace != personIdByIris) + { + // 人脸和虹膜识别的不是同一人 识别失败 + LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); + SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); + showRecogFailure(); + } else + { + LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); + showRecognizeResult(personId); + + // 识别记录存入数据库 + RecognitionRecordDao recDao; + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("type", "3"); + record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); + recDao.save(record); + } } - - if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) - { - // 只有一个成功的结果 需要等待下次 - return; - } else if (personIdByFace != personIdByIris) - { - // 人脸和虹膜识别的不是同一人 识别失败 - LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); - SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); - showRecogFailure(); - } else - { - LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); - showRecognizeResult(personId); - } - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - ProMemory::getInstance().clearFaceQueue(); - ProMemory::getInstance().faceRecogPro->setWorking(false); - ProMemory::getInstance().faceCam->stopTakingPhoto(); - - // 识别记录存入数据库 - RecognitionRecordDao recDao; - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("type", "4"); - record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); - recDao.save(record); } } + +void RecognizeResultForm::updateRecogTips(QString tipsText) +{ + ui->labTitle->setText(tipsText); +} +void RecognizeResultForm::updateRecogTipsColor(QString bgColor) +{ + ui->labTitle->setStyleSheet("background: " + bgColor); +} diff --git a/RecognizeResultForm.h b/RecognizeResultForm.h index 2c51865..65dd8ad 100644 --- a/RecognizeResultForm.h +++ b/RecognizeResultForm.h @@ -30,6 +30,8 @@ void startWorkingRecognize(); // 开始工作 void drawImageOnHomeForm(QImage imageDisp); + void updateRecogTips(QString tipsText); + void updateRecogTipsColor(QString bgColor); private: Ui::RecognizeResultForm *ui; diff --git a/StartupForm.cpp b/StartupForm.cpp index 16c4dfc..cf20de1 100644 --- a/StartupForm.cpp +++ b/StartupForm.cpp @@ -20,17 +20,23 @@ } // 设置弹簧的高度和宽度 - ui->vsTop->changeSize(0, 200); - ui->vsMidd->changeSize(0, 100); ui->hsLeft->changeSize(400, 0); ui->hsMidd->changeSize(150, 0); + // 绑定时间和日期的标签单击事件 单击即开始识别 + connect(ui->labDate, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + connect(ui->labTime, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + // 初始化更新界面的定时器 // 每秒执行一次 connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &StartupForm::updateDateAndTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, - this, &StartupForm::takeOneFrameForCheckStatus); +// connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, +// this, &StartupForm::takeOneFrameForCheckStatus); TimeCounterUtil::getInstance().clockCounter->start(1000); } diff --git a/StartupForm.h b/StartupForm.h index f2850e9..fc79be0 100644 --- a/StartupForm.h +++ b/StartupForm.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "casic/ProMemory.h" #include "utils/UtilInclude.h" diff --git a/StartupForm.ui b/StartupForm.ui index afb610f..de353f3 100644 --- a/StartupForm.ui +++ b/StartupForm.ui @@ -15,20 +15,7 @@ - - - Qt::Vertical - - - - 17 - 166 - - - - - - + TextLabel @@ -38,7 +25,7 @@ - + TextLabel @@ -48,19 +35,6 @@ - - - Qt::Vertical - - - - 17 - 167 - - - - - @@ -158,6 +132,13 @@ + + + QDblClickLabel + QLabel +
QDblClickLabel.h
+
+
diff --git a/casic/ProMemory.h b/casic/ProMemory.h index 3e9fbd4..02a14cf 100644 --- a/casic/ProMemory.h +++ b/casic/ProMemory.h @@ -16,6 +16,8 @@ #include "device/face/FaceRecogProcess.h" #include "device/iris/IrisRegistProcess.h" #include "device/iris/IrisRecogProcess.h" +#include "device/MotoController.h" +#include "device/CameraPositionController.h" class FaceCameraController; class IrisCameraController; @@ -23,6 +25,8 @@ class FaceRecogProcess; class IrisRegistProcess; class IrisRecogProcess; +class MotoController; +class CameraPositionController; class ProMemory { @@ -66,6 +70,10 @@ IrisRegistProcess * irisRegistPro; IrisRecogProcess * irisRecogPro; + MotoController * moto; + + CameraPositionController * camPosCtrl; + private: ProMemory(); diff --git a/casic/face/CasicFaceInterface.cpp b/casic/face/CasicFaceInterface.cpp index f530212..3cb2118 100644 --- a/casic/face/CasicFaceInterface.cpp +++ b/casic/face/CasicFaceInterface.cpp @@ -45,8 +45,6 @@ delete this->cascade; this->cascade = nullptr; } - - LOG(DEBUG) << "delete models in destructor"; } void casic::face::CasicFaceInterface::setDetectorModelPath(std::string detectorModelPath) @@ -384,6 +382,9 @@ cv::Size minRectSize(minFaceSize, minFaceSize); cv::Size maxRectSize(maxFaceSize, maxFaceSize); + QElapsedTimer timer; + timer.start(); + // ★分类器对象调用 cascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); @@ -391,6 +392,8 @@ { return cv::Rect(0, 0, 0, 0); } + + LOG(DEBUG) << QString("人脸分类检测算法[tm: %1 ms][%2, %3]").arg(timer.elapsed()).arg(rect.at(0).width).arg(rect.at(0).height).toStdString(); return rect.at(0); } @@ -424,7 +427,7 @@ return rect.at(0); } -bool casic::face::CasicFaceInterface::hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize) +std::vector casic::face::CasicFaceInterface::eyeDetectByCVCascade(cv::Mat frame, int minEyeSize) { // 构建openCV自带的眼睛分类器 if (this->eyeCascade == nullptr) @@ -433,14 +436,14 @@ this->eyeCascade->load(cvEyeCascadeName); } - std::vector rect; + std::vector rectVec; cv::Size minRectSize(minEyeSize, minEyeSize); cv::Size maxRectSize(maxEyeSize, maxEyeSize); // ★分类器对象调用 - eyeCascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); + eyeCascade->detectMultiScale(frame, rectVec, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); - return rect.size() == 0 ? false : true; + return rectVec; } void casic::face::CasicFaceInterface::setMinFaceSize(int minFaceSize) diff --git a/casic/face/CasicFaceInterface.h b/casic/face/CasicFaceInterface.h index 9d8b8ea..1753bd1 100644 --- a/casic/face/CasicFaceInterface.h +++ b/casic/face/CasicFaceInterface.h @@ -52,7 +52,7 @@ cv::Rect faceDetectByCVCascade(cv::Mat frame, int minFaceSize); cv::Rect eyeDetectByCVCascade(cv::Mat frame); - bool hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize); + std::vector eyeDetectByCVCascade(cv::Mat frame, int minEyeSize); void setMinFaceSize(int minFaceSize); void setMinEyeSize(int minEyeSize); private: diff --git a/dao/RecognitionRecordDao.cpp b/dao/RecognitionRecordDao.cpp index 403894a..d7103f9 100644 --- a/dao/RecognitionRecordDao.cpp +++ b/dao/RecognitionRecordDao.cpp @@ -91,13 +91,14 @@ .arg(object.value("type").toString()) .arg(object.value("dev_code").toString()) .arg(object.value("door_code").toString()) - .arg(object.value("inout_type").toString()); + .arg(object.value("inout_type").toString()) + .arg(object.value("debug_info").toString()); query.prepare(sql); LOG(DEBUG) << sql.toStdString(); // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES ('%1', '%2')") + QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES ('%1', '%2')") .arg(id).arg(object.value("debug_info").toString()); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/device/CameraPositionController.cpp b/device/CameraPositionController.cpp new file mode 100644 index 0000000..577c9ad --- /dev/null +++ b/device/CameraPositionController.cpp @@ -0,0 +1,91 @@ +#include "CameraPositionController.h" + +CameraPositionController::CameraPositionController(QObject *parent) : QThread(parent) +{ + this->working = false; + this->exit = false; +} + +CameraPositionController::~CameraPositionController() +{ + this->setWorking(false); +} + +void CameraPositionController::setWorking(bool working) +{ + this->working = working; +} +void CameraPositionController::exitThread() +{ + this->working = false; + this->exit = true; +} + +void CameraPositionController::run() +{ + while (exit == false) + { + if (this->working == false) + { + this->msleep(200); // 200ms后再判断 + continue; + } + + // 取一幅图像 + cv::Mat rawFrame = ProMemory::getInstance().faceCam->takeOneRawFrame(); +/* + // 分类器找眼睛 + cv::Rect eyeRect = casic::face::CasicFaceInterface::getInstance().eyeDetectByCVCascade(rawFrame); + if (eyeRect.width != 0) + { + // 眼睛的位置 + int eyeCenter = eyeRect.y + eyeRect.height / 2; + LOG(DEBUG) << eyeCenter << " " << abs(eyeCenter - 300) << " " << 100 * abs(eyeCenter - 300) / 20 + 200; + + if (eyeCenter < 250 || eyeCenter > 350) + { +// ProMemory::getInstance().moto->autoPosition(eyeCenter); + emit motoControl(eyeCenter); + +// this->msleep(100 * abs(eyeCenter - 300) / 20 + 200); // 200ms后再判断 + } + } + */ + + // 分类器找脸 + cv::Rect faceRect = casic::face::CasicFaceInterface::getInstance().faceDetectByCVCascade(rawFrame, SettingConfig::getInstance().MIN_WORK_FACE_SIZE); + QString facePos = QString("%1 * %2, (%3, %4), (%5, %6)").arg(faceRect.width).arg(faceRect.height) + .arg(faceRect.x).arg(faceRect.y).arg(faceRect.x + faceRect.width).arg(faceRect.y + faceRect.height); + + if (faceRect.width != 0) + { + // 通过人脸的大小判断距离,提示靠近或者远离 + if (faceRect.width < 360) + { + emit updateTips(QString("距离太远,请靠近 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#9F1919"); + } else if (faceRect.width >= 360 && faceRect.width <= 480) + { + emit updateTips(QString("正在识别,请保持 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#248A53"); + + // 位置合适 开始识别 +// ProMemory::getInstance().irisRecogPro->setWorking(true); +// ProMemory::getInstance().irisCam->startCapture(); +// this->setWorking(false); + } else if (faceRect.width > 480) + { + emit updateTips(QString("距离太近,请远离 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#9F1919"); + } + } + + this->msleep(500); + } +} + + +void CameraPositionController::checkFacePosition() +{ + +} diff --git a/device/CameraPositionController.h b/device/CameraPositionController.h new file mode 100644 index 0000000..9520b14 --- /dev/null +++ b/device/CameraPositionController.h @@ -0,0 +1,39 @@ +#ifndef CAMERAPOSITIONCONTROLLER_H +#define CAMERAPOSITIONCONTROLLER_H + +#include +#include + +#include "opencv2/opencv.hpp" +#include "utils/UtilInclude.h" +#include "casic/ProMemory.h" + +class CameraPositionController : public QThread +{ + Q_OBJECT +public: + explicit CameraPositionController(QObject *parent = 0); + ~CameraPositionController(); + + void setWorking(bool working); + void exitThread(); + +protected: + //QThread的虚函数 + //线程处理函数 + //不能直接调用, 通过start()间接调用 + void run(); + + volatile bool working; + volatile bool exit; + +public slots: + void checkFacePosition(); + +signals: + void updateTips(QString tipsText); + void updateTipsBackgroundColor(QString bgColor); + void motoControl(int eyeCenter); +}; + +#endif // CAMERAPOSITIONCONTROLLER_H diff --git a/device/FaceCameraController.cpp b/device/FaceCameraController.cpp index 0fe4b4c..2a4d7cb 100644 --- a/device/FaceCameraController.cpp +++ b/device/FaceCameraController.cpp @@ -41,8 +41,7 @@ void FaceCameraController::closeFaceCamera() { faceCap->release(); - - delete faceCap; +// delete faceCap; } @@ -88,7 +87,7 @@ // 拍图 faceCap->read(faceMat); - LOG(TRACE) << "TAKE ONE FACE FRAME " << faceMat.cols << " * " << faceMat.rows; + LOG(TRACE) << QThread::currentThreadId() << " TAKE ONE FACE FRAME " << faceMat.cols << " * " << faceMat.rows; // 左右翻转 cv::Mat imageMatMiir; diff --git a/device/MotoController.cpp b/device/MotoController.cpp new file mode 100644 index 0000000..15cb5f0 --- /dev/null +++ b/device/MotoController.cpp @@ -0,0 +1,127 @@ +#include "MotoController.h" + + +MotoController::MotoController(QObject *parent) : QObject(parent) +{ + this->portName = "COM2"; + this->baudRate = "9600"; +} + + +bool MotoController::initSerialMCU() +{ + QList list = QSerialPortInfo::availablePorts(); + if (list.isEmpty() == true) + return false; + + this->portName = SettingConfig::getInstance().PORT_NAME; + + serial.setPortName(this->portName); + serial.setBaudRate(this->baudRate.toInt()); + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); + + bool succ = serial.open(QIODevice::ReadWrite); + + //连接信号和槽 + + LOG(DEBUG) << QString("[MotoController][initSerialMCU]打开电机串口[%1][%2][%3]").arg(portName).arg(baudRate).arg(succ).toStdString(); + + return succ; +} + +void MotoController::sendDataAutoEnding(QByteArray data) +{ + LOG(INFO) << QString("向串口发送数据[send] %1").arg(data.data()).toStdString(); + + // 加上0x0D 0x0A换行结束 + data.append(0x0D).append(0x0A); + serial.write(data); +} + + +/** + * @brief MotoController::encodeProtocol + * @param content + * @return + * 格式 +0000 00 长度=9 + * bit1 = +/- +表示向上运动 -表示向下运动 + * bit2-bit4 表示调整的量 + * bit5 开关灯控制量 + * bit6 空格 + * bit7-bit8 数值的累加和 + * bit9 空格 + */ +QByteArray MotoController::encodeProtocol(QString content) +{ + if (content.toInt() > 0) + { + content = "+" + content; + } + + // 调整数值的绝对值 三位数字 + int abs = content.mid(1, content.length()).toInt(); + + // 补齐3位数值 + if (abs < 10) + { + content.insert(1, "00"); + } else if (abs < 100) + { + content.insert(1, "0"); + } + + // 计算累加和 + int sum = 0; + for (int i = 0; i < content.mid(1, content.length()).length(); i++) + { + sum += content.mid(i + 1, 1).toInt(); + } + + // 格式化累加和字符串 + QString sumStr = QString::number(sum); + if (sumStr.length() == 1) + { + sumStr.prepend("0"); + } else if (sumStr.length() > 2) + { + sumStr = QString::number(sum).mid(0, 2); + } + + // 开关灯的控制量 = 0 + content.append("0"); + content = content.append(0x20).append(sumStr).append(0x20); + + return content.toUtf8(); +} + +void MotoController::autoFacePosition(CasicFaceInfo * faceInfo) +{ + if (faceInfo->hasFace == false) + { + return; + } + + const int centerLine = 300; + int faceTop = faceInfo->faceRecTL[1]; + int faceCenterLine = faceTop + faceInfo->face.pos.height / 2; + + int diff = (faceCenterLine - centerLine) * -0.8; + QByteArray data = this->encodeProtocol(QString::number(diff)); + this->sendDataAutoEnding(data); +} + +void MotoController::autoPosition(int eyeCenter) +{ + int center = 300; + int dir = eyeCenter > center ? -1 : 1; + int step = abs(eyeCenter - center) / 20; + for (int i = 0; i < step; i++) + { + QByteArray data = this->encodeProtocol(QString::number(20 * dir)); + this->sendDataAutoEnding(data); + QThread::msleep(100); + } +} diff --git a/device/MotoController.h b/device/MotoController.h new file mode 100644 index 0000000..60aa5dc --- /dev/null +++ b/device/MotoController.h @@ -0,0 +1,39 @@ +#ifndef MOTOCONTROLLER_H +#define MOTOCONTROLLER_H + +#include +#include +#include +#include + +#include "casic/face/CasicFaceInfo.h" +#include "utils/UtilInclude.h" + +class MotoController : public QObject +{ + Q_OBJECT +public: + explicit MotoController(QObject *parent = nullptr); + + // 打开串口 + bool initSerialMCU(); + +public slots: + void autoFacePosition(CasicFaceInfo * faceInfo); + void autoPosition(int eyeCenter); + +private: + QSerialPort serial; + QString portName; + QString baudRate; + + QByteArray buffRecv; + + QByteArray encodeProtocol(QString content); + void sendDataAutoEnding(QByteArray data); + +signals: + +}; + +#endif // MOTOCONTROLLER_H diff --git a/device/device.pri b/device/device.pri index 64e6e17..2a1b90b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,10 +1,12 @@ -HEADERS += $$PWD/FaceCameraController.h +HEADERS += $$PWD/FaceCameraController.h \ + $$PWD/CameraPositionController.h HEADERS += $$PWD/face/FaceRecogProcess.h HEADERS += $$PWD/face/FaceRegistProcess.h HEADERS += $$PWD/face/CasicFaceRecState.h -SOURCES += $$PWD/FaceCameraController.cpp +SOURCES += $$PWD/FaceCameraController.cpp \ + $$PWD/CameraPositionController.cpp SOURCES += $$PWD/face/FaceRecogProcess.cpp SOURCES += $$PWD/face/FaceRegistProcess.cpp SOURCES += $$PWD/face/CasicFaceRecState.cpp @@ -14,11 +16,14 @@ HEADERS += $$PWD/iris/IrisRegistProcess.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h -#HEADERS += $$PWD/MotoController.h SOURCES += $$PWD/IrisCameraController.cpp SOURCES += $$PWD/IrisCameraCapEventHandler.cpp SOURCES += $$PWD/iris/IrisRegistProcess.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp -#SOURCES += $$PWD/MotoController.cpp + +HEADERS += $$PWD/MotoController.h +SOURCES += $$PWD/MotoController.cpp +HEADERS += +SOURCES += diff --git a/qss/startup.css b/qss/startup.css index 9c9b4d6..77027e8 100644 --- a/qss/startup.css +++ b/qss/startup.css @@ -4,11 +4,13 @@ } QLabel#labDate { - font-size: 36px; + font-size: 48px; + padding-bottom: 100px; } QLabel#labTime { font-size: 100px; + padding-top: 200px; } QToolButton { diff --git a/utils/TimeCounterUtil.cpp b/utils/TimeCounterUtil.cpp index 275945f..e69de29 100644 --- a/utils/TimeCounterUtil.cpp +++ b/utils/TimeCounterUtil.cpp @@ -1,8 +0,0 @@ -#include "TimeCounterUtil.h" - -TimeCounterUtil::TimeCounterUtil() -{ - faceCapCounter = new QTimer(); - irisCapCounter = new QTimer(); - clockCounter = new QTimer(); -} diff --git a/utils/TimeCounterUtil.h b/utils/TimeCounterUtil.h index 28b29f1..4e22acb 100644 --- a/utils/TimeCounterUtil.h +++ b/utils/TimeCounterUtil.h @@ -22,7 +22,12 @@ QTimer * clockCounter; private: - TimeCounterUtil(); + TimeCounterUtil() + { + faceCapCounter = new QTimer(); + irisCapCounter = new QTimer(); + clockCounter = new QTimer(); + } }; diff --git a/AddPersonForm.cpp b/AddPersonForm.cpp index 05fe5f1..97b10d6 100644 --- a/AddPersonForm.cpp +++ b/AddPersonForm.cpp @@ -155,6 +155,10 @@ ui->labPhotoEyeLeft->setPixmap(QPixmap(":/images/photoEyeLeft.png")); ui->labPhotoEyeRight->setPixmap(QPixmap(":/images/photoEyeRight.png")); + + faceCode = ""; + leftIrisCode = ""; + rightIrisCode = ""; } void AddPersonForm::drawImageOnForm(QImage imageDisp) @@ -683,6 +687,7 @@ faceLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_FACE; + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRegistPro->setWorking(true); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -714,5 +719,6 @@ rightIrisLabel->show(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::ADD_PERSON_CAPTURE_IRIS; + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRegistPro->setWorking(true); // 开始工作 } diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp index f202cfe..bc8018b 100644 --- a/CasicBioRecWin.cpp +++ b/CasicBioRecWin.cpp @@ -6,7 +6,7 @@ , ui(new Ui::CasicBioRecWin) { // 打开外部可执行程序 - outExe = new QProcess(this); +// outExe = new QProcess(this); // outExe->start(SettingConfig::getInstance().OUT_EXE_FILE); ui->setupUi(this); @@ -31,6 +31,7 @@ initFaceRecogThread(); // 人脸识别线程 initIrisRegistThread(); // 虹膜注册线程 initIrisRecogThread(); // 虹膜识别线程 + initCameraPositionThread(); // 调整相机位置 // 初始化人脸相机控制 ProMemory::getInstance().faceCam = new FaceCameraController(this); @@ -49,6 +50,12 @@ connect(ProMemory::getInstance().irisCam->rightHandler, &IrisCameraCapEventHandler::sendIrisFrameToDraw, addPersonForm, &AddPersonForm::drawIrisImageOnFrame); + // 初始化电机控制 + ProMemory::getInstance().moto = new MotoController(this); + ProMemory::getInstance().moto->initSerialMCU(); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::motoControl, + ProMemory::getInstance().moto, &MotoController::autoPosition); + // 打印日志 LOG(INFO) << QString("应用程序启动成功[Application Startup Success]").toStdString(); ProMemory::getInstance().widgeFrame = CasicBioRecConst::WidgeFrameName::MAIN_PAGE; @@ -72,6 +79,10 @@ ProMemory::getInstance().irisRecogPro->deleteLater(); ProMemory::getInstance().irisRecogPro->wait(); + ProMemory::getInstance().camPosCtrl->exitThread(); + ProMemory::getInstance().camPosCtrl->deleteLater(); + ProMemory::getInstance().camPosCtrl->wait(); + // 关闭自动启动的外部程序 // outExe->close(); // delete outExe; @@ -81,12 +92,14 @@ delete ProMemory::getInstance().faceRecogPro; delete ProMemory::getInstance().irisRegistPro; delete ProMemory::getInstance().irisRecogPro; + delete ProMemory::getInstance().camPosCtrl; } void CasicBioRecWin::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: + LOG(INFO) << "" << std::endl; QTimer::singleShot(100, qApp, SLOT(quit())); default: @@ -204,8 +217,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().faceRecogPro, &FaceRecogProcess::matchSuccess, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -244,8 +255,6 @@ // 绑定信号与槽函数 // 识别成功 -// connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, -// recogResultForm, &RecognizeResultForm::showRecognizeResult); connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, recogResultForm, &RecognizeResultForm::checkRecognizeResult); @@ -255,3 +264,17 @@ ProMemory::getInstance().irisRecogPro->start(); } + +void CasicBioRecWin::initCameraPositionThread() +{ + // 调整相机位置处理 + ProMemory::getInstance().camPosCtrl = new CameraPositionController(this); + + // 绑定信号与槽函数 + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTips, + recogResultForm, &RecognizeResultForm::updateRecogTips); + connect(ProMemory::getInstance().camPosCtrl, &CameraPositionController::updateTipsBackgroundColor, + recogResultForm, &RecognizeResultForm::updateRecogTipsColor); + + ProMemory::getInstance().camPosCtrl->start(); +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h index b70245a..b5a3db9 100644 --- a/CasicBioRecWin.h +++ b/CasicBioRecWin.h @@ -54,6 +54,7 @@ void initFaceRecogThread(); void initIrisRegistThread(); void initIrisRecogThread(); + void initCameraPositionThread(); }; #endif // CASICBIORECWIN_H diff --git a/RecognizeResultForm.cpp b/RecognizeResultForm.cpp index e45a191..b340be9 100644 --- a/RecognizeResultForm.cpp +++ b/RecognizeResultForm.cpp @@ -20,7 +20,7 @@ RecognizeResultForm::~RecognizeResultForm() { - delete ui; + delete ui; } void RecognizeResultForm::startWorkingRecognize() @@ -29,23 +29,32 @@ switch (SettingConfig::getInstance().RECOG_TYPE) { case 1: // 人脸识别 + ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); break; case 2: // 虹膜识别 + ProMemory::getInstance().clearIrisQueue(); +// ProMemory::getInstance().camPosCtrl->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; case 3: + // 双认证 先打开人脸识别 成功后再进行虹膜识别 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(true); + break; case 4: // 人脸和虹膜都需要打开 + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().faceRecogPro->setWorking(true); ProMemory::getInstance().irisRecogPro->setWorking(true); ProMemory::getInstance().irisCam->startCapture(); break; } - // 将界面切换到识别界面 RecognizeResultForm + // 开始拍图并显示视频 ProMemory::getInstance().faceCam->openFaceCamera(SettingConfig::getInstance().FACE_FRAME_INTERVAL); ui->labBackground->raise(); @@ -80,6 +89,14 @@ ui->widgetFail->raise(); ui->widgetFail->show(); + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().camPosCtrl->setWorking(false); + + ProMemory::getInstance().clearFaceQueue(); + ProMemory::getInstance().faceRecogPro->setWorking(false); + QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){ ui->labBackground->raise(); CasicFaceRecState::getInstance().state = CasicFaceRecState::REC_NOT_START; @@ -137,9 +154,9 @@ case 1: { // 仅人脸识别 - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); LOG(DEBUG) << QString("[RecognizeResultForm] 人脸识别成功 [%1]").arg(CasicFaceRecState::getInstance().toString()).toStdString(); @@ -158,9 +175,12 @@ case 2: { // 仅虹膜识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + // 停止控制电机和提示 + ProMemory::getInstance().camPosCtrl->setWorking(false); LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜识别成功 [%1]").arg(CasicIrisRecState::getInstance().toString()).toStdString(); @@ -179,13 +199,13 @@ case 4: { // 任意识别 - ProMemory::getInstance().clearIrisQueue(); ProMemory::getInstance().irisRecogPro->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().clearFaceQueue(); ProMemory::getInstance().faceRecogPro->setWorking(false); ProMemory::getInstance().faceCam->stopTakingPhoto(); + ProMemory::getInstance().clearFaceQueue(); QString logStr = QString("[RecognizeResultForm]%1识别成功[%2]"); if (faceOrIris == 1) @@ -213,42 +233,56 @@ if (faceOrIris == 1) { this->personIdByFace = personId; + + // 人脸识别成功后 开始进行虹膜识别 + // 1. 首先停止人脸识别 + ProMemory::getInstance().faceRecogPro->setWorking(false); + ProMemory::getInstance().clearFaceQueue(); + + // 2. 虹膜识别开始 + ProMemory::getInstance().clearIrisQueue(); + ProMemory::getInstance().camPosCtrl->setWorking(true); } else if (faceOrIris == 2) { this->personIdByIris = personId; + + ProMemory::getInstance().irisRecogPro->setWorking(false); + ProMemory::getInstance().irisCam->stopCapture(); + ProMemory::getInstance().clearIrisQueue(); + + if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) + { + // 只有一个成功的结果 需要等待下次 + return; + } else if (personIdByFace != personIdByIris) + { + // 人脸和虹膜识别的不是同一人 识别失败 + LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); + SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); + showRecogFailure(); + } else + { + LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); + showRecognizeResult(personId); + + // 识别记录存入数据库 + RecognitionRecordDao recDao; + QVariantMap record; + record.insert("person_id", personId); + record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); + record.insert("type", "3"); + record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); + recDao.save(record); + } } - - if (personIdByFace.isEmpty() || personIdByIris.isEmpty()) - { - // 只有一个成功的结果 需要等待下次 - return; - } else if (personIdByFace != personIdByIris) - { - // 人脸和虹膜识别的不是同一人 识别失败 - LOG(DEBUG) << QString("[RecognizeResultForm] 虹膜与人脸识别结果不一致,识别失败 [face: %1][iris: %2]").arg(personIdByFace).arg(personIdByIris).toStdString(); - SpeakerUtil::getInstance().speak("虹膜与人脸识别结果不一致,识别失败,请重试"); - showRecogFailure(); - } else - { - LOG(DEBUG) << QString("[RecognizeResultForm]人脸虹膜识别成功").toStdString(); - showRecognizeResult(personId); - } - - ProMemory::getInstance().clearIrisQueue(); - ProMemory::getInstance().irisRecogPro->setWorking(false); - ProMemory::getInstance().irisCam->stopCapture(); - - ProMemory::getInstance().clearFaceQueue(); - ProMemory::getInstance().faceRecogPro->setWorking(false); - ProMemory::getInstance().faceCam->stopTakingPhoto(); - - // 识别记录存入数据库 - RecognitionRecordDao recDao; - QVariantMap record; - record.insert("person_id", personId); - record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); - record.insert("type", "4"); - record.insert("debug_info", CasicFaceRecState::getInstance().toString() + " " + CasicIrisRecState::getInstance().toString()); - recDao.save(record); } } + +void RecognizeResultForm::updateRecogTips(QString tipsText) +{ + ui->labTitle->setText(tipsText); +} +void RecognizeResultForm::updateRecogTipsColor(QString bgColor) +{ + ui->labTitle->setStyleSheet("background: " + bgColor); +} diff --git a/RecognizeResultForm.h b/RecognizeResultForm.h index 2c51865..65dd8ad 100644 --- a/RecognizeResultForm.h +++ b/RecognizeResultForm.h @@ -30,6 +30,8 @@ void startWorkingRecognize(); // 开始工作 void drawImageOnHomeForm(QImage imageDisp); + void updateRecogTips(QString tipsText); + void updateRecogTipsColor(QString bgColor); private: Ui::RecognizeResultForm *ui; diff --git a/StartupForm.cpp b/StartupForm.cpp index 16c4dfc..cf20de1 100644 --- a/StartupForm.cpp +++ b/StartupForm.cpp @@ -20,17 +20,23 @@ } // 设置弹簧的高度和宽度 - ui->vsTop->changeSize(0, 200); - ui->vsMidd->changeSize(0, 100); ui->hsLeft->changeSize(400, 0); ui->hsMidd->changeSize(150, 0); + // 绑定时间和日期的标签单击事件 单击即开始识别 + connect(ui->labDate, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + connect(ui->labTime, &QDblClickLabel::clicked, this, [=]() { + emit startRecognize(); + }); + // 初始化更新界面的定时器 // 每秒执行一次 connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &StartupForm::updateDateAndTime); - connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, - this, &StartupForm::takeOneFrameForCheckStatus); +// connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, +// this, &StartupForm::takeOneFrameForCheckStatus); TimeCounterUtil::getInstance().clockCounter->start(1000); } diff --git a/StartupForm.h b/StartupForm.h index f2850e9..fc79be0 100644 --- a/StartupForm.h +++ b/StartupForm.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "casic/ProMemory.h" #include "utils/UtilInclude.h" diff --git a/StartupForm.ui b/StartupForm.ui index afb610f..de353f3 100644 --- a/StartupForm.ui +++ b/StartupForm.ui @@ -15,20 +15,7 @@ - - - Qt::Vertical - - - - 17 - 166 - - - - - - + TextLabel @@ -38,7 +25,7 @@ - + TextLabel @@ -48,19 +35,6 @@ - - - Qt::Vertical - - - - 17 - 167 - - - - - @@ -158,6 +132,13 @@ + + + QDblClickLabel + QLabel +
QDblClickLabel.h
+
+
diff --git a/casic/ProMemory.h b/casic/ProMemory.h index 3e9fbd4..02a14cf 100644 --- a/casic/ProMemory.h +++ b/casic/ProMemory.h @@ -16,6 +16,8 @@ #include "device/face/FaceRecogProcess.h" #include "device/iris/IrisRegistProcess.h" #include "device/iris/IrisRecogProcess.h" +#include "device/MotoController.h" +#include "device/CameraPositionController.h" class FaceCameraController; class IrisCameraController; @@ -23,6 +25,8 @@ class FaceRecogProcess; class IrisRegistProcess; class IrisRecogProcess; +class MotoController; +class CameraPositionController; class ProMemory { @@ -66,6 +70,10 @@ IrisRegistProcess * irisRegistPro; IrisRecogProcess * irisRecogPro; + MotoController * moto; + + CameraPositionController * camPosCtrl; + private: ProMemory(); diff --git a/casic/face/CasicFaceInterface.cpp b/casic/face/CasicFaceInterface.cpp index f530212..3cb2118 100644 --- a/casic/face/CasicFaceInterface.cpp +++ b/casic/face/CasicFaceInterface.cpp @@ -45,8 +45,6 @@ delete this->cascade; this->cascade = nullptr; } - - LOG(DEBUG) << "delete models in destructor"; } void casic::face::CasicFaceInterface::setDetectorModelPath(std::string detectorModelPath) @@ -384,6 +382,9 @@ cv::Size minRectSize(minFaceSize, minFaceSize); cv::Size maxRectSize(maxFaceSize, maxFaceSize); + QElapsedTimer timer; + timer.start(); + // ★分类器对象调用 cascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); @@ -391,6 +392,8 @@ { return cv::Rect(0, 0, 0, 0); } + + LOG(DEBUG) << QString("人脸分类检测算法[tm: %1 ms][%2, %3]").arg(timer.elapsed()).arg(rect.at(0).width).arg(rect.at(0).height).toStdString(); return rect.at(0); } @@ -424,7 +427,7 @@ return rect.at(0); } -bool casic::face::CasicFaceInterface::hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize) +std::vector casic::face::CasicFaceInterface::eyeDetectByCVCascade(cv::Mat frame, int minEyeSize) { // 构建openCV自带的眼睛分类器 if (this->eyeCascade == nullptr) @@ -433,14 +436,14 @@ this->eyeCascade->load(cvEyeCascadeName); } - std::vector rect; + std::vector rectVec; cv::Size minRectSize(minEyeSize, minEyeSize); cv::Size maxRectSize(maxEyeSize, maxEyeSize); // ★分类器对象调用 - eyeCascade->detectMultiScale(frame, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); + eyeCascade->detectMultiScale(frame, rectVec, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minRectSize, maxRectSize); - return rect.size() == 0 ? false : true; + return rectVec; } void casic::face::CasicFaceInterface::setMinFaceSize(int minFaceSize) diff --git a/casic/face/CasicFaceInterface.h b/casic/face/CasicFaceInterface.h index 9d8b8ea..1753bd1 100644 --- a/casic/face/CasicFaceInterface.h +++ b/casic/face/CasicFaceInterface.h @@ -52,7 +52,7 @@ cv::Rect faceDetectByCVCascade(cv::Mat frame, int minFaceSize); cv::Rect eyeDetectByCVCascade(cv::Mat frame); - bool hasEyeDetectedByCVCascade(cv::Mat frame, int minEyeSize); + std::vector eyeDetectByCVCascade(cv::Mat frame, int minEyeSize); void setMinFaceSize(int minFaceSize); void setMinEyeSize(int minEyeSize); private: diff --git a/dao/RecognitionRecordDao.cpp b/dao/RecognitionRecordDao.cpp index 403894a..d7103f9 100644 --- a/dao/RecognitionRecordDao.cpp +++ b/dao/RecognitionRecordDao.cpp @@ -91,13 +91,14 @@ .arg(object.value("type").toString()) .arg(object.value("dev_code").toString()) .arg(object.value("door_code").toString()) - .arg(object.value("inout_type").toString()); + .arg(object.value("inout_type").toString()) + .arg(object.value("debug_info").toString()); query.prepare(sql); LOG(DEBUG) << sql.toStdString(); // 插入识别的log日志 - QString logStr = QString("INSERT INTO RECOGNITION_LOG (ID, LOG_INFO) VALUES ('%1', '%2')") + QString logStr = QString("INSERT INTO RECOGNITION_LOGS (ID, LOG_INFO) VALUES ('%1', '%2')") .arg(id).arg(object.value("debug_info").toString()); QSqlQuery logQuery(ConnectionManager::getInstance()->getConnection()); logQuery.prepare(logStr); diff --git a/device/CameraPositionController.cpp b/device/CameraPositionController.cpp new file mode 100644 index 0000000..577c9ad --- /dev/null +++ b/device/CameraPositionController.cpp @@ -0,0 +1,91 @@ +#include "CameraPositionController.h" + +CameraPositionController::CameraPositionController(QObject *parent) : QThread(parent) +{ + this->working = false; + this->exit = false; +} + +CameraPositionController::~CameraPositionController() +{ + this->setWorking(false); +} + +void CameraPositionController::setWorking(bool working) +{ + this->working = working; +} +void CameraPositionController::exitThread() +{ + this->working = false; + this->exit = true; +} + +void CameraPositionController::run() +{ + while (exit == false) + { + if (this->working == false) + { + this->msleep(200); // 200ms后再判断 + continue; + } + + // 取一幅图像 + cv::Mat rawFrame = ProMemory::getInstance().faceCam->takeOneRawFrame(); +/* + // 分类器找眼睛 + cv::Rect eyeRect = casic::face::CasicFaceInterface::getInstance().eyeDetectByCVCascade(rawFrame); + if (eyeRect.width != 0) + { + // 眼睛的位置 + int eyeCenter = eyeRect.y + eyeRect.height / 2; + LOG(DEBUG) << eyeCenter << " " << abs(eyeCenter - 300) << " " << 100 * abs(eyeCenter - 300) / 20 + 200; + + if (eyeCenter < 250 || eyeCenter > 350) + { +// ProMemory::getInstance().moto->autoPosition(eyeCenter); + emit motoControl(eyeCenter); + +// this->msleep(100 * abs(eyeCenter - 300) / 20 + 200); // 200ms后再判断 + } + } + */ + + // 分类器找脸 + cv::Rect faceRect = casic::face::CasicFaceInterface::getInstance().faceDetectByCVCascade(rawFrame, SettingConfig::getInstance().MIN_WORK_FACE_SIZE); + QString facePos = QString("%1 * %2, (%3, %4), (%5, %6)").arg(faceRect.width).arg(faceRect.height) + .arg(faceRect.x).arg(faceRect.y).arg(faceRect.x + faceRect.width).arg(faceRect.y + faceRect.height); + + if (faceRect.width != 0) + { + // 通过人脸的大小判断距离,提示靠近或者远离 + if (faceRect.width < 360) + { + emit updateTips(QString("距离太远,请靠近 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#9F1919"); + } else if (faceRect.width >= 360 && faceRect.width <= 480) + { + emit updateTips(QString("正在识别,请保持 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#248A53"); + + // 位置合适 开始识别 +// ProMemory::getInstance().irisRecogPro->setWorking(true); +// ProMemory::getInstance().irisCam->startCapture(); +// this->setWorking(false); + } else if (faceRect.width > 480) + { + emit updateTips(QString("距离太近,请远离 %1").arg(faceRect.width)); + emit updateTipsBackgroundColor("#9F1919"); + } + } + + this->msleep(500); + } +} + + +void CameraPositionController::checkFacePosition() +{ + +} diff --git a/device/CameraPositionController.h b/device/CameraPositionController.h new file mode 100644 index 0000000..9520b14 --- /dev/null +++ b/device/CameraPositionController.h @@ -0,0 +1,39 @@ +#ifndef CAMERAPOSITIONCONTROLLER_H +#define CAMERAPOSITIONCONTROLLER_H + +#include +#include + +#include "opencv2/opencv.hpp" +#include "utils/UtilInclude.h" +#include "casic/ProMemory.h" + +class CameraPositionController : public QThread +{ + Q_OBJECT +public: + explicit CameraPositionController(QObject *parent = 0); + ~CameraPositionController(); + + void setWorking(bool working); + void exitThread(); + +protected: + //QThread的虚函数 + //线程处理函数 + //不能直接调用, 通过start()间接调用 + void run(); + + volatile bool working; + volatile bool exit; + +public slots: + void checkFacePosition(); + +signals: + void updateTips(QString tipsText); + void updateTipsBackgroundColor(QString bgColor); + void motoControl(int eyeCenter); +}; + +#endif // CAMERAPOSITIONCONTROLLER_H diff --git a/device/FaceCameraController.cpp b/device/FaceCameraController.cpp index 0fe4b4c..2a4d7cb 100644 --- a/device/FaceCameraController.cpp +++ b/device/FaceCameraController.cpp @@ -41,8 +41,7 @@ void FaceCameraController::closeFaceCamera() { faceCap->release(); - - delete faceCap; +// delete faceCap; } @@ -88,7 +87,7 @@ // 拍图 faceCap->read(faceMat); - LOG(TRACE) << "TAKE ONE FACE FRAME " << faceMat.cols << " * " << faceMat.rows; + LOG(TRACE) << QThread::currentThreadId() << " TAKE ONE FACE FRAME " << faceMat.cols << " * " << faceMat.rows; // 左右翻转 cv::Mat imageMatMiir; diff --git a/device/MotoController.cpp b/device/MotoController.cpp new file mode 100644 index 0000000..15cb5f0 --- /dev/null +++ b/device/MotoController.cpp @@ -0,0 +1,127 @@ +#include "MotoController.h" + + +MotoController::MotoController(QObject *parent) : QObject(parent) +{ + this->portName = "COM2"; + this->baudRate = "9600"; +} + + +bool MotoController::initSerialMCU() +{ + QList list = QSerialPortInfo::availablePorts(); + if (list.isEmpty() == true) + return false; + + this->portName = SettingConfig::getInstance().PORT_NAME; + + serial.setPortName(this->portName); + serial.setBaudRate(this->baudRate.toInt()); + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); + + bool succ = serial.open(QIODevice::ReadWrite); + + //连接信号和槽 + + LOG(DEBUG) << QString("[MotoController][initSerialMCU]打开电机串口[%1][%2][%3]").arg(portName).arg(baudRate).arg(succ).toStdString(); + + return succ; +} + +void MotoController::sendDataAutoEnding(QByteArray data) +{ + LOG(INFO) << QString("向串口发送数据[send] %1").arg(data.data()).toStdString(); + + // 加上0x0D 0x0A换行结束 + data.append(0x0D).append(0x0A); + serial.write(data); +} + + +/** + * @brief MotoController::encodeProtocol + * @param content + * @return + * 格式 +0000 00 长度=9 + * bit1 = +/- +表示向上运动 -表示向下运动 + * bit2-bit4 表示调整的量 + * bit5 开关灯控制量 + * bit6 空格 + * bit7-bit8 数值的累加和 + * bit9 空格 + */ +QByteArray MotoController::encodeProtocol(QString content) +{ + if (content.toInt() > 0) + { + content = "+" + content; + } + + // 调整数值的绝对值 三位数字 + int abs = content.mid(1, content.length()).toInt(); + + // 补齐3位数值 + if (abs < 10) + { + content.insert(1, "00"); + } else if (abs < 100) + { + content.insert(1, "0"); + } + + // 计算累加和 + int sum = 0; + for (int i = 0; i < content.mid(1, content.length()).length(); i++) + { + sum += content.mid(i + 1, 1).toInt(); + } + + // 格式化累加和字符串 + QString sumStr = QString::number(sum); + if (sumStr.length() == 1) + { + sumStr.prepend("0"); + } else if (sumStr.length() > 2) + { + sumStr = QString::number(sum).mid(0, 2); + } + + // 开关灯的控制量 = 0 + content.append("0"); + content = content.append(0x20).append(sumStr).append(0x20); + + return content.toUtf8(); +} + +void MotoController::autoFacePosition(CasicFaceInfo * faceInfo) +{ + if (faceInfo->hasFace == false) + { + return; + } + + const int centerLine = 300; + int faceTop = faceInfo->faceRecTL[1]; + int faceCenterLine = faceTop + faceInfo->face.pos.height / 2; + + int diff = (faceCenterLine - centerLine) * -0.8; + QByteArray data = this->encodeProtocol(QString::number(diff)); + this->sendDataAutoEnding(data); +} + +void MotoController::autoPosition(int eyeCenter) +{ + int center = 300; + int dir = eyeCenter > center ? -1 : 1; + int step = abs(eyeCenter - center) / 20; + for (int i = 0; i < step; i++) + { + QByteArray data = this->encodeProtocol(QString::number(20 * dir)); + this->sendDataAutoEnding(data); + QThread::msleep(100); + } +} diff --git a/device/MotoController.h b/device/MotoController.h new file mode 100644 index 0000000..60aa5dc --- /dev/null +++ b/device/MotoController.h @@ -0,0 +1,39 @@ +#ifndef MOTOCONTROLLER_H +#define MOTOCONTROLLER_H + +#include +#include +#include +#include + +#include "casic/face/CasicFaceInfo.h" +#include "utils/UtilInclude.h" + +class MotoController : public QObject +{ + Q_OBJECT +public: + explicit MotoController(QObject *parent = nullptr); + + // 打开串口 + bool initSerialMCU(); + +public slots: + void autoFacePosition(CasicFaceInfo * faceInfo); + void autoPosition(int eyeCenter); + +private: + QSerialPort serial; + QString portName; + QString baudRate; + + QByteArray buffRecv; + + QByteArray encodeProtocol(QString content); + void sendDataAutoEnding(QByteArray data); + +signals: + +}; + +#endif // MOTOCONTROLLER_H diff --git a/device/device.pri b/device/device.pri index 64e6e17..2a1b90b 100644 --- a/device/device.pri +++ b/device/device.pri @@ -1,10 +1,12 @@ -HEADERS += $$PWD/FaceCameraController.h +HEADERS += $$PWD/FaceCameraController.h \ + $$PWD/CameraPositionController.h HEADERS += $$PWD/face/FaceRecogProcess.h HEADERS += $$PWD/face/FaceRegistProcess.h HEADERS += $$PWD/face/CasicFaceRecState.h -SOURCES += $$PWD/FaceCameraController.cpp +SOURCES += $$PWD/FaceCameraController.cpp \ + $$PWD/CameraPositionController.cpp SOURCES += $$PWD/face/FaceRecogProcess.cpp SOURCES += $$PWD/face/FaceRegistProcess.cpp SOURCES += $$PWD/face/CasicFaceRecState.cpp @@ -14,11 +16,14 @@ HEADERS += $$PWD/iris/IrisRegistProcess.h HEADERS += $$PWD/iris/IrisRecogProcess.h HEADERS += $$PWD/iris/CasicIrisRecState.h -#HEADERS += $$PWD/MotoController.h SOURCES += $$PWD/IrisCameraController.cpp SOURCES += $$PWD/IrisCameraCapEventHandler.cpp SOURCES += $$PWD/iris/IrisRegistProcess.cpp SOURCES += $$PWD/iris/IrisRecogProcess.cpp SOURCES += $$PWD/iris/CasicIrisRecState.cpp -#SOURCES += $$PWD/MotoController.cpp + +HEADERS += $$PWD/MotoController.h +SOURCES += $$PWD/MotoController.cpp +HEADERS += +SOURCES += diff --git a/qss/startup.css b/qss/startup.css index 9c9b4d6..77027e8 100644 --- a/qss/startup.css +++ b/qss/startup.css @@ -4,11 +4,13 @@ } QLabel#labDate { - font-size: 36px; + font-size: 48px; + padding-bottom: 100px; } QLabel#labTime { font-size: 100px; + padding-top: 200px; } QToolButton { diff --git a/utils/TimeCounterUtil.cpp b/utils/TimeCounterUtil.cpp index 275945f..e69de29 100644 --- a/utils/TimeCounterUtil.cpp +++ b/utils/TimeCounterUtil.cpp @@ -1,8 +0,0 @@ -#include "TimeCounterUtil.h" - -TimeCounterUtil::TimeCounterUtil() -{ - faceCapCounter = new QTimer(); - irisCapCounter = new QTimer(); - clockCounter = new QTimer(); -} diff --git a/utils/TimeCounterUtil.h b/utils/TimeCounterUtil.h index 28b29f1..4e22acb 100644 --- a/utils/TimeCounterUtil.h +++ b/utils/TimeCounterUtil.h @@ -22,7 +22,12 @@ QTimer * clockCounter; private: - TimeCounterUtil(); + TimeCounterUtil() + { + faceCapCounter = new QTimer(); + irisCapCounter = new QTimer(); + clockCounter = new QTimer(); + } }; diff --git a/utils/utils.pri b/utils/utils.pri index b3d3d63..0e76395 100644 --- a/utils/utils.pri +++ b/utils/utils.pri @@ -13,7 +13,7 @@ SOURCES += $$PWD/SettingConfig.cpp HEADERS += $$PWD/TimeCounterUtil.h -SOURCES += $$PWD/TimeCounterUtil.cpp +#SOURCES += $$PWD/TimeCounterUtil.cpp HEADERS += $$PWD/SelectDeptUtil.h SOURCES += $$PWD/SelectDeptUtil.cpp