#include "faceLiveness.h" #include "ui_faceLiveness.h" #include "CAppInfo.h" #include #include #include #include "awMsgBox.h" #include "logproc.h" #include "CCommonTools.h" #include "CFaceRecProc.h" faceLiveness::faceLiveness(FACE_LIVENESS_TYPE livenessType, QWidget *parent) : QWidget(parent), ui(new Ui::faceLiveness), m_livenessType(livenessType) { ui->setupUi(this); setStyleSheet(g_appInfoPtr->m_sQssStr); initUI(); qRegisterMetaType("CBaseResponsePackage"); qRegisterMetaType("CClientExamProcessUploadSign"); qRegisterMetaType("CUploadFileToAliyun"); connect(g_httpBllPtr.get(), &CHttpBll::sgnClientExamProcessUploadSign, this, &faceLiveness::onClientExamProcessUploadSign); connect(g_httpBllPtr.get(), &CHttpBll::sgnSaveFaceLiveVerifyResult, this, &faceLiveness::onSaveFaceLiveVerifyResult); connect(g_httpBllPtr.get(), &CHttpBll::sgnSaveFaceCompareResult, this, &faceLiveness::onSaveFaceCompareResult); connect(g_httpBllPtr.get(), &CHttpBll::sgnUploadFileToAliyun, this, &faceLiveness::onUploadFileToAliyun); if(m_livenessType == FACE_LIVENESS_TYPE::flt_inprogress) { ui->label_fl_time->setVisible(true); ui->btn_fl_close->setVisible(false); myServerLog()<< "FACE_LIVENESS_TYPE::flt_inprogress"; } else { ui->label_fl_time->setVisible(false); ui->btn_fl_close->setVisible(true); myServerLog()<< "FACE_LIVENESS_TYPE::flt_entry_exam"; } m_nMaxSeconds = g_appInfoPtr->m_oExamInfo.nAllActionDuration; QString sFileName = g_appInfoPtr->m_sStudentPhotoPath.right(g_appInfoPtr->m_sStudentPhotoPath.length() - g_appInfoPtr->m_sStudentPhotoPath.lastIndexOf("/") - 1); sFileName = g_appInfoPtr->m_sCacheFileDir + sFileName; if(!QFile::exists(sFileName)) { CHttpRequestPackage hrp; hrp.sUri = g_appInfoPtr->m_sStudentPhotoPath; hrp.sCommonStr = sFileName; hrp.nRequestType = RequestType::rtDownLoadFile; hrp.nRetryCount = 3; g_httpBllPtr->downLoad(hrp); } m_pVideoTimer = std::make_shared(); m_pVideoTimer->setInterval(200); connect(m_pVideoTimer.get(), &QTimer::timeout, this, [&](){ cv::Mat frame; { std::scoped_lock sl(m_imageMutex); frame = m_nCurImage; } QImage img = CCommonTools::Mat2QImage(frame); ui->widget_fc_camera->setAutoFillBackground(true); QPalette palette; palette.setBrush(QPalette::Window, QBrush(img.scaled(ui->widget_fc_camera->width(), ui->widget_fc_camera->height()))); ui->widget_fc_camera->setPalette(palette); if(m_bStartCompare && !frame.empty()) { std::scoped_lock sl(m_imgMutex); m_imgList.push_back(frame); } }); g_clientVideoProcPtr->startTest(this); m_pVideoTimer->start(); //生成动作列表 QStringList sActionList = g_appInfoPtr->m_oExamInfo.sActionOptions.split(","); if(sActionList.count() != g_appInfoPtr->m_oExamInfo.nActionNum) { ShowMsg(QString::fromLocal8Bit("初始化活体动作失败"), this, MSG_ICON_TYPE::mit_error); emit faceLivenessFaild(); return; } LivenessVerifyInfo lvif; lvif.sActionType = ACTION_TYPE::AT_FACE_DETECT; lvif.nActionLeftSceonds = m_nFaceDetectDuration; m_livenessList.push_back(lvif); m_currentVerifyInfo = lvif; if(g_appInfoPtr->m_oExamInfo.sActionOrder == "FIXED") { for(QString sAction : sActionList) { LivenessVerifyInfo lvi; lvi.sActionType = sAction; lvi.nActionLeftSceonds = g_appInfoPtr->m_oExamInfo.nActionDuration; m_livenessList.push_back(lvi); } } else { QList list; CCommonTools::genRandomNumber(list, g_appInfoPtr->m_oExamInfo.nActionNum); for(int i = 0; i < g_appInfoPtr->m_oExamInfo.nActionNum; i++) { LivenessVerifyInfo lvi; lvi.sActionType = sActionList[list[i]-1]; lvi.nActionLeftSceonds = g_appInfoPtr->m_oExamInfo.nActionDuration; m_livenessList.push_back(lvi); } } m_nCurIndex = 0; m_ActionTimer = std::make_shared(); m_ActionTimer->setInterval(1000); connect(m_ActionTimer.get(), &QTimer::timeout, this, &faceLiveness::actionTimer); m_countdownTimer = std::make_shared(); m_countdownTimer->setInterval(1000); connect(m_countdownTimer.get(), &QTimer::timeout, this, &faceLiveness::countdownTimer); m_countdownTimer->start(); m_bIsRun = true; m_thread = std::thread(std::bind(&faceLiveness::threadProc, this)); m_initTimer = std::make_shared(); m_initTimer->setInterval(100); connect(m_initTimer.get(), &QTimer::timeout, this, [&](){ m_initTimer->stop(); if(g_faceRecProcPtr == nullptr) { g_faceRecProcPtr = std::make_shared(); } if (!g_appInfoPtr->m_sStudentPhotoPath.isEmpty()) { // if(!g_faceRecProcPtr->hasBaseImage()) { if(!setBaseImage()) { return; } } } else { ShowMsg(QString::fromLocal8Bit("当前考试未底照"), this, MSG_ICON_TYPE::mit_error); return; } // if(!g_faceRecProcPtr->hasBaseImage()) // { // if(!setBaseImage()) // { // return; // } // } m_bStartCompare = true; m_fMaxYaw = 0; m_fMinYaw = 0; m_sLivenessStatus = STATUS_TYPE::ST_SUCCESS; { std::scoped_lock sl(m_livenessListMutex); m_currentVerifyInfo = m_livenessList[m_nCurIndex]; } initAcionIcon(); m_ActionTimer->start(); }); m_initTimer->start(); } faceLiveness::~faceLiveness() { m_pVideoTimer->stop(); m_ActionTimer->stop(); g_clientVideoProcPtr->stopTest(); m_bIsRun = false; m_thread.join(); awMsgBox::clear(this); delete ui; } void faceLiveness::onRenderVideoFrame(const char* userId, TRTCVideoStreamType streamType, TRTCVideoFrame* frame) { if(g_clientVideoProcPtr->isCameraTest()) { __int64 nServerTime = g_appInfoPtr->serverMTime(); if(nServerTime - m_lastFaceTime >= 100) { m_lastFaceTime = nServerTime; cv::Mat matImg; cv::cvtColor(cv::Mat(frame->height, frame->width, CV_8UC4, frame->data), matImg, CV_RGBA2RGB); if(matImg.empty()) { qDebug()<<"widgetCameraTest frame is empty"; return; } std::scoped_lock sl(m_imageMutex); m_nCurImage = matImg; } } } void faceLiveness::initUI() { QDesktopWidget *dekwiget = QApplication::desktop(); setGeometry(0, 0, dekwiget->width(), dekwiget->height()); ui->widget_mask->setGeometry(0, 0, dekwiget->width(), dekwiget->height()); ui->widget_fc_BG->setGeometry((width() - g_appInfoPtr->m_fRate*800)/2, (height() - g_appInfoPtr->m_fRate*536)/2, g_appInfoPtr->m_fRate*800, g_appInfoPtr->m_fRate*536); ui->label_fl_title->adjustSize(); ui->label_fl_title->setGeometry(g_appInfoPtr->m_fRate*20, g_appInfoPtr->m_fRate*20, ui->label_fl_title->width(), ui->label_fl_title->height()); ui->label_fl_time->setGeometry(ui->label_fl_title->x() + ui->label_fl_title->width(), ui->label_fl_title->y(), g_appInfoPtr->m_fRate*200, ui->label_fl_title->height()); ui->btn_fl_close->setGeometry(ui->widget_fc_BG->width() - g_appInfoPtr->m_fRate*(20 + 100), g_appInfoPtr->m_fRate*16, g_appInfoPtr->m_fRate*100, g_appInfoPtr->m_fRate*36); ui->widget_fc_camera->setGeometry(g_appInfoPtr->m_fRate*30, g_appInfoPtr->m_fRate*75, g_appInfoPtr->m_fRate*740, g_appInfoPtr->m_fRate*320); ui->btn_fl_startVerify->setGeometry((ui->widget_fc_camera->width() - g_appInfoPtr->m_fRate*160)/2, ui->widget_fc_camera->y() + ui->widget_fc_camera->height() + g_appInfoPtr->m_fRate*30, g_appInfoPtr->m_fRate*160, g_appInfoPtr->m_fRate*40); ui->label_fl_tips->adjustSize(); ui->label_fl_tips->setGeometry((ui->widget_fc_BG->width() - ui->label_fl_tips->width())/2, ui->btn_fl_startVerify->y() + ui->btn_fl_startVerify->height() + g_appInfoPtr->m_fRate*20, ui->label_fl_tips->width(), ui->label_fl_tips ->height()); ui->label_fl_actionMoive->setGeometry(0, 0, g_appInfoPtr->m_fRate*64, g_appInfoPtr->m_fRate*64); ui->label_fl_actionTips->adjustSize(); int nActionWidth = ui->label_fl_actionMoive->width() + g_appInfoPtr->m_fRate*20 + ui->label_fl_actionTips->width() + g_appInfoPtr->m_fRate*20 + g_appInfoPtr->m_fRate*44; ui->widget_fl_action->setGeometry((ui->widget_fc_camera->width() - nActionWidth)/2, g_appInfoPtr->m_fRate*10, nActionWidth, g_appInfoPtr->m_fRate*64) ; ui->label_fl_actionTips->setGeometry(ui->label_fl_actionMoive->x() + ui->label_fl_actionMoive->width() + g_appInfoPtr->m_fRate*20, (ui->widget_fl_action->height() - ui->label_fl_actionTips->height())/2, ui->label_fl_actionTips->width(), ui->label_fl_actionTips->height()); ui->btn_fl_time->setGeometry(ui->label_fl_actionTips->x() + ui->label_fl_actionTips->width() + g_appInfoPtr->m_fRate*20, (ui->widget_fl_action->height() - g_appInfoPtr->m_fRate*40)/2, g_appInfoPtr->m_fRate*40, g_appInfoPtr->m_fRate*40); ui->widget_fl_hint->setVisible(false); ui->widget_fl_hint->setGeometry((width() - g_appInfoPtr->m_fRate*400)/2, (height() - g_appInfoPtr->m_fRate*180)/2, g_appInfoPtr->m_fRate*400, g_appInfoPtr->m_fRate*180); ui->label_fl_icon->setGeometry(g_appInfoPtr->m_fRate*75, g_appInfoPtr->m_fRate*70, g_appInfoPtr->m_fRate*40, g_appInfoPtr->m_fRate*40); ui->label_fl_hint->adjustSize(); ui->label_fl_hint->setGeometry(ui->label_fl_icon->x() + ui->label_fl_icon->width() + g_appInfoPtr->m_fRate*20, ui->label_fl_icon->y() + (ui->label_fl_icon->height() - ui->label_fl_hint->height())/2, ui->label_fl_hint->width(), ui->label_fl_hint->height()); ui->widget_fl_action->setVisible(false); ui->btn_fl_startVerify->setVisible(false); ui->label_fl_tips->setVisible(false); ui->widget_fc_camera->setFixedHeight(g_appInfoPtr->m_fRate*431); ui->widget_fl_action->setVisible(true); } void faceLiveness::threadProc() { try { while (m_bIsRun) { if (m_bStartCompare) { if (m_imgList.begin() != m_imgList.end()) { myServerLog() << "m_imgList:" << m_imgList.size(); cv::Mat matImage; { std::scoped_lock lock(m_imgMutex); if (m_imgList.begin() != m_imgList.end()) { matImage = (*m_imgList.begin()).clone(); m_imgList.erase(m_imgList.begin()); } else { continue; } } if (matImage.empty()) { myServerLog() << "matImage.empty"; continue; } if (!m_currentVerifyInfo.bIsVerify) { verifyAction(matImage); } } } else { Sleep(100); } } } catch (const std::exception &e) { myDebug()<compareWithBase(matImage, nFaceCount, fScore, rt)) { m_currentVerifyInfo.sErrorMsg = g_faceRecProcPtr->errorMsg(); myServerLog() << g_faceRecProcPtr->errorMsg(); return; } m_currentVerifyInfo.nFaceCount = nFaceCount; m_currentVerifyInfo.fSimilarity = fScore; if (nFaceCount != 1) { myServerLog() << QString::fromLocal8Bit("活体检测人脸数量异常,") << nFaceCount; m_currentVerifyInfo.sErrorMsg = QString::fromLocal8Bit("活体检测人脸数量异常,").arg(nFaceCount); return; } if (fScore * 100 > g_appInfoPtr->m_oExamInfo.nFaceThreshold) { bool bRealness = false; if (!g_faceRecProcPtr->faceRealness(matImage, bRealness)) { myServerLog() << g_faceRecProcPtr->errorMsg(); m_currentVerifyInfo.sErrorMsg = g_faceRecProcPtr->errorMsg(); return; } //验证成功 if (bRealness) { m_currentVerifyInfo.nEndTime = g_appInfoPtr->serverMTime(); m_currentVerifyInfo.nRealness = 1; m_currentVerifyInfo.bPass = true; m_currentVerifyInfo.bIsVerify = true; myServerLog() << m_currentVerifyInfo.sActionType << ":" << fScore; return; } else { m_currentVerifyInfo.nRealness = 0; } } } if (m_currentVerifyInfo.sActionType == ACTION_TYPE::AT_BLINK || m_currentVerifyInfo.sActionType == ACTION_TYPE::AT_NOD) { int nFaceStatus = 0; if (m_currentVerifyInfo.sActionType == ACTION_TYPE::AT_BLINK) { nFaceStatus = SL_EYE_CLOSE; } else { nFaceStatus = SL_HEAD_DOWN; } if (!g_faceRecProcPtr->getFaceAttribute(matImage, nFaceStatus, bHasStatus, nFaceCount)) { myServerLog() << g_faceRecProcPtr->errorMsg(); m_currentVerifyInfo.sErrorMsg = g_faceRecProcPtr->errorMsg(); return; } m_currentVerifyInfo.nFaceCount = nFaceCount; if (nFaceCount != 1) { myServerLog() << QString::fromLocal8Bit("活体检测人脸数量异常,") << nFaceCount; m_currentVerifyInfo.sErrorMsg = QString::fromLocal8Bit("活体检测人脸数量异常,").arg(nFaceCount); return; } if (bHasStatus) { //验证成功 m_currentVerifyInfo.nEndTime = g_appInfoPtr->serverMTime(); m_currentVerifyInfo.nRealness = 1; m_currentVerifyInfo.bPass = true; m_currentVerifyInfo.bIsVerify = true; } } else if (m_currentVerifyInfo.sActionType == ACTION_TYPE::AT_SHAKE) { float fYaw = 0; float fPitch = 0; float fRoll = 0; int nFaceCount = 0; if (!g_faceRecProcPtr->getFaceAttribute(matImage, fYaw, fPitch, fRoll, nFaceCount)) { myServerLog() << g_faceRecProcPtr->errorMsg(); m_currentVerifyInfo.sErrorMsg = g_faceRecProcPtr->errorMsg(); return; } m_currentVerifyInfo.nFaceCount = nFaceCount; if (m_fMinYaw > fYaw) { m_fMinYaw = fYaw; } if (m_fMaxYaw < fYaw) { m_fMaxYaw = fYaw; } if (m_fMaxYaw - m_fMinYaw > 30) { //验证成功 m_currentVerifyInfo.nEndTime = g_appInfoPtr->serverMTime(); m_currentVerifyInfo.nRealness = 1; m_currentVerifyInfo.bPass = true; m_currentVerifyInfo.bIsVerify = true; } } } catch (const std::exception &e) { myDebug() << QString::fromLocal8Bit("人脸比对失败,%1").arg(e.what()); } } bool faceLiveness::setBaseImage() { QString sFileName = g_appInfoPtr->m_sStudentPhotoPath.right(g_appInfoPtr->m_sStudentPhotoPath.length() - g_appInfoPtr->m_sStudentPhotoPath.lastIndexOf("/") - 1); sFileName = g_appInfoPtr->m_sCacheFileDir + sFileName; if(!QFile::exists(sFileName)) { ShowMsg(QString::fromLocal8Bit("底照下载失败,请检查网络"), this, MSG_ICON_TYPE::mit_error); return false; } QFileInfo filePath(sFileName); if(!g_faceRecProcPtr->setBaseImage(filePath.absoluteFilePath())) { //g_faceRecProcPtr->errorMsg() ShowMsg(QString::fromLocal8Bit("底照不符合要求,请更换照片"), this, MSG_ICON_TYPE::mit_error); return false; } return true; } void faceLiveness::on_btn_fl_startVerify_clicked() { if(g_faceRecProcPtr == nullptr) { g_faceRecProcPtr = std::make_shared(); } if (!g_appInfoPtr->m_sStudentPhotoPath.isEmpty()) { // if(!g_faceRecProcPtr->hasBaseImage()) { if(!setBaseImage()) { return; } } } else { ShowMsg(QString::fromLocal8Bit("当前考试未底照"), this, MSG_ICON_TYPE::mit_error); return; } // if(!g_faceRecProcPtr->hasBaseImage()) // { // if(!setBaseImage()) // { // return; // } // } m_bStartCompare = true; m_fMaxYaw = 0; m_fMinYaw = 0; m_sLivenessStatus = STATUS_TYPE::ST_SUCCESS; ui->btn_fl_startVerify->setVisible(false); ui->label_fl_tips->setVisible(false); ui->widget_fc_camera->setFixedHeight(g_appInfoPtr->m_fRate*431); ui->widget_fl_action->setVisible(true); { std::scoped_lock sl(m_livenessListMutex); m_currentVerifyInfo = m_livenessList[m_nCurIndex]; } initAcionIcon(); m_ActionTimer->start(); } void faceLiveness::initAcionIcon() { QMovie *movie; ui->btn_fl_time->setVisible(true); ui->btn_fl_time->setText(QString("%1s").arg(m_currentVerifyInfo.nActionLeftSceonds)); if(m_currentVerifyInfo.sActionType == ACTION_TYPE::AT_FACE_DETECT) { movie = new QMovie(":/images/img-fl-face.png"); ui->label_fl_actionTips->setText(QString::fromLocal8Bit("请让我看到您的正脸")); //ui->btn_fl_time->setVisible(false); } else if(m_currentVerifyInfo.sActionType == ACTION_TYPE::AT_BLINK) { movie = new QMovie(":/images/gif-close-eyes.gif"); ui->label_fl_actionTips->setText(QString::fromLocal8Bit("请闭眼")); } else if(m_currentVerifyInfo.sActionType == ACTION_TYPE::AT_SHAKE) { movie = new QMovie(":/images/gif-turn-head.gif"); ui->label_fl_actionTips->setText(QString::fromLocal8Bit("请摇头")); } else if(m_currentVerifyInfo.sActionType == ACTION_TYPE::AT_NOD) { movie = new QMovie(":/images/gif-head-down.gif"); ui->label_fl_actionTips->setText(QString::fromLocal8Bit("请点头")); } ui->label_fl_actionMoive->setMovie(movie); movie->start(); } void faceLiveness:: saveLivenessResult() { try { bool bSubmit = true; for (int i = 0; i < m_livenessList.count(); ++i) { if(m_livenessList[i].matImage.empty()) { myServerLog()<post(hrp); break; } } if (bSubmit) { bool bSucceed = true; Json::Value jLiveness = Json::Value::null; jLiveness["status"] = m_sLivenessStatus.toStdString(); jLiveness["faceLiveVerifyId"] = g_appInfoPtr->m_oExamInfo.nFaceLiveVerifyId; jLiveness["processTime"] = m_nEndTime - m_nStartTime; for (int i = 0; i < m_livenessList.count(); ++i) { if (m_livenessList[i].sActionType == ACTION_TYPE::AT_FACE_DETECT) { jLiveness["examRecordDataId"] = g_appInfoPtr->m_oExamInfo.nExamRecordDataId; jLiveness["faceCount"] = m_livenessList[i].nFaceCount; jLiveness["realness"] = m_livenessList[i].nRealness; jLiveness["similarity"] = m_livenessList[i].fSimilarity; jLiveness["fileUrl"] = m_livenessList[i].sUrl.toStdString(); if (m_livenessList[i].nFaceCount == 0) { jLiveness["status"] = STATUS_TYPE::ST_NOT_ONESELF.toStdString(); } } else { Json::Value jAction = Json::Value::null; if (!m_livenessList[i].bPass) { bSucceed = false; jAction["errorMsg"] = m_livenessList[i].sErrorMsg.toStdString(); } jAction["fileUrl"] = m_livenessList[i].sUrl.toStdString(); jAction["pass"] = m_livenessList[i].bPass; jAction["processTime"] = m_livenessList[i].nEndTime - m_livenessList[i].nStartTime; jAction["retry"] = 0; jAction["type"] = m_livenessList[i].sActionType.toStdString(); jLiveness["actions"].append(jAction); } } myServerLog() << jLiveness.toStyledString().c_str(); CHttpRequestPackage hrp; hrp.sUri = QString("/api/ecs_oe_student/client/exam/process/saveFaceLiveVerifyResult"); hrp.nRequestType = RequestType::rtSaveFaceLiveVerifyResult; hrp.eParamType = HttpParamType::hptCustomBody; hrp.sParamList.push_back(QString("CustomBody,%1").arg(jLiveness.toStyledString().c_str())); g_httpBllPtr->post(hrp); } } catch (const std::exception &e) { myDebug() << QString::fromLocal8Bit("人脸比对失败,%1").arg(e.what()); } } void faceLiveness::countdownTimer() { try { --m_nMaxSeconds; ui->label_fl_time->setText(QString("(%1)").arg(m_nMaxSeconds)); if(m_livenessType == FACE_LIVENESS_TYPE::flt_inprogress && m_nMaxSeconds <= 0) { //整体超时 m_bStartCompare = false; m_ActionTimer->stop(); m_countdownTimer->stop(); { std::scoped_lock sl(m_livenessListMutex); m_livenessList[m_nCurIndex] = m_currentVerifyInfo; } m_sLivenessStatus = STATUS_TYPE::ST_TIME_OUT; saveLivenessResult(); } } catch (const std::exception &e) { myDebug() << QString::fromLocal8Bit("人脸比对失败,%1").arg(e.what()); } } void faceLiveness::actionTimer() { try { if (m_currentVerifyInfo.bIsVerify && !m_currentVerifyInfo.matImage.empty()) { //当前比对完成 { std::scoped_lock sl(m_livenessListMutex); m_livenessList[m_nCurIndex] = m_currentVerifyInfo; } //下一个动作 ++m_nCurIndex; if (m_nCurIndex < m_livenessList.count()) { std::scoped_lock sl(m_livenessListMutex); m_currentVerifyInfo = m_livenessList[m_nCurIndex]; m_currentVerifyInfo.reset(m_livenessList[m_nCurIndex].sActionType == ACTION_TYPE ::AT_FACE_DETECT ? m_nFaceDetectDuration : g_appInfoPtr->m_oExamInfo.nActionDuration); initAcionIcon(); { std::scoped_lock sl(m_imgMutex); m_imgList.clear(); } } else { //整体比对完成 m_sLivenessStatus = STATUS_TYPE::ST_SUCCESS; m_bStartCompare = false; m_ActionTimer->stop(); m_countdownTimer->stop(); saveLivenessResult(); return; } } else { if (m_currentVerifyInfo.nActionLeftSceonds <= 0) { ++m_nFaceRetryCount; { std::scoped_lock sl(m_imgMutex); m_imgList.clear(); } if(m_nFaceRetryCount >= m_nMaxFaceRetryCount) { if(m_nFaceWholeRetryCount >= m_nMaxFaceWholeRetryCount) { //整体失败 m_bStartCompare = false; m_currentVerifyInfo.sErrorMsg = QString::fromLocal8Bit("action timeout"); m_ActionTimer->stop(); m_countdownTimer->stop(); { std::scoped_lock sl(m_livenessListMutex); m_livenessList[m_nCurIndex] = m_currentVerifyInfo; } m_sLivenessStatus = STATUS_TYPE::ST_TIME_OUT; if(m_livenessType == FACE_LIVENESS_TYPE::flt_inprogress) { saveLivenessResult(); } else { showVerifyResultUI(); QTimer::singleShot(2000, this, [&]() { emit faceLivenessFaild(); }); } return; } ++m_nFaceWholeRetryCount; { std::scoped_lock sl(m_imgMutex); m_imgList.clear(); } m_nFaceRetryCount = 0; m_nCurIndex = 0; if (m_nCurIndex < m_livenessList.count()) { std::scoped_lock sl(m_livenessListMutex); m_currentVerifyInfo = m_livenessList[m_nCurIndex]; m_currentVerifyInfo.reset(m_livenessList[m_nCurIndex].sActionType == ACTION_TYPE::AT_FACE_DETECT ? m_nFaceDetectDuration : g_appInfoPtr->m_oExamInfo.nActionDuration); initAcionIcon(); } return; } ++m_nFaceRetryCount; m_currentVerifyInfo.reset(m_currentVerifyInfo.sActionType == ACTION_TYPE::AT_FACE_DETECT ? m_nFaceDetectDuration : g_appInfoPtr->m_oExamInfo.nActionDuration); initAcionIcon(); } else { --m_currentVerifyInfo.nActionLeftSceonds; ui->btn_fl_time->setText(QString("%1s").arg(m_currentVerifyInfo.nActionLeftSceonds)); if(m_currentVerifyInfo.sActionType == ACTION_TYPE::AT_FACE_DETECT) { if(m_currentVerifyInfo.nActionLeftSceonds == 50) { ShowMsg(QString::fromLocal8Bit("人脸检测不通过(请调整角度和光线进行尝试,不要戴眼镜)"), (QWidget*)this->parent()); } else if(m_currentVerifyInfo.nActionLeftSceonds == 30) { ShowMsg(QString::fromLocal8Bit("人脸检测不通过(请调整角度和光线进行尝试,不要戴眼镜)"), (QWidget*)this->parent()); } else if(m_currentVerifyInfo.nActionLeftSceonds == 1) { ShowMsg(QString::fromLocal8Bit("若多次尝试不通过,请联系老师更换照片后重试"), (QWidget*)this->parent()); } } } } } catch (const std::exception &e) { myDebug() << QString::fromLocal8Bit("人脸比对失败,%1").arg(e.what()); } } //文件上传 void faceLiveness::onClientExamProcessUploadSign(CClientExamProcessUploadSign processUpload) { try { if(processUpload.sCommonStr == __FILE__) { if(processUpload.nCode == 200) { m_nRetryCount = 0; CHttpRequestPackage hrp; hrp.sUri = processUpload.sFormUrl; hrp.nRequestType = RequestType::rtUploadFileToAliyun; hrp.sCommonStr = __FILE__; hrp.sCommonStr1 = processUpload.sAccessUrl; hrp.sParamList.push_back(QString("OSSAccessKeyId,%1").arg(processUpload.sOssAcessKeyId)); hrp.sParamList.push_back(QString("Signature,%1").arg(processUpload.sSignature)); hrp.sParamList.push_back(QString("key,%1").arg(processUpload.sKey)); hrp.sParamList.push_back(QString("policy,%1").arg(processUpload.sPolicy)); hrp.sParamList.push_back(QString("success_action_status,%1").arg(200)); hrp.sParamList.push_back(QString("formdataFileType,file,%1").arg(processUpload.sFilePath)); hrp.bNoHostPrefix = true; hrp.eParamType = HttpParamType::hptFormdata; g_httpBllPtr->post(hrp); } else { if(processUpload.sMessage.isEmpty()) { ShowMsg(QString::fromLocal8Bit("上传照片失败"), this, MSG_ICON_TYPE::mit_error); } else { ShowMsg(processUpload.sMessage, this, MSG_ICON_TYPE::mit_error); } if(m_nRetryCount < 4) { saveLivenessResult(); m_nRetryCount++; } else { emit faceLivenessFaild(); } } } } catch (const std::exception &e) { ShowMsg(QString::fromLocal8Bit("上传照片失败"), this, MSG_ICON_TYPE::mit_error); myServerLog()<<"exception error"< 1; hrp.sParamList.push_back(QString("CustomBody,%1").arg(jBody.toStyledString().c_str())); hrp.eParamType = HttpParamType::hptCustomBody; g_httpBllPtr->post(hrp); } void faceLiveness::onSaveFaceCompareResult(CBaseResponsePackage res) { try { if(res.nCode == 200) { m_nRetryCount = 0; saveLivenessResult(); } else { if(m_nRetryCount < 4) { saveFaceCampareResult(); m_nRetryCount++; } else { emit faceLivenessFaild(); } } } catch (const std::exception &e) { ShowMsg(QString::fromLocal8Bit("保存人脸识别信息失败"), this, MSG_ICON_TYPE::mit_error); myServerLog()<<"exception error"<label_fl_hint->setText(QString::fromLocal8Bit("恭喜您完成检测!")); ui->label_fl_icon->setPixmap(QPixmap(":/images/icon-welcom.png")); } else if(m_sLivenessStatus == STATUS_TYPE::ST_TIME_OUT) { ui->label_fl_hint->setText(QString::fromLocal8Bit("检测失败:活体检测超时")); ui->label_fl_icon->setPixmap(QPixmap(":/images/icon-liveness-faild.png")); } else { ui->label_fl_hint->setText(QString::fromLocal8Bit("检测失败:单个动作超时")); ui->label_fl_icon->setPixmap(QPixmap(":/images/icon-liveness-faild.png")); } ui->label_fl_hint->adjustSize(); ui->widget_fc_BG->setVisible(false); ui->widget_fl_hint->setVisible(true); ui->widget_fl_hint->setGeometry((width() - ui->label_fl_hint->width() - g_appInfoPtr->m_fRate * 180) / 2, (height() - g_appInfoPtr->m_fRate * 180) / 2, ui->label_fl_hint->width() + g_appInfoPtr->m_fRate * 180, g_appInfoPtr->m_fRate * 180); ui->label_fl_icon->setGeometry(g_appInfoPtr->m_fRate * 75, g_appInfoPtr->m_fRate * 70, g_appInfoPtr->m_fRate * 40, g_appInfoPtr->m_fRate * 40); ui->label_fl_hint->setGeometry(ui->label_fl_icon->x() + ui->label_fl_icon->width() + g_appInfoPtr->m_fRate * 20, ui->label_fl_icon->y() + (ui->label_fl_icon->height() - ui->label_fl_hint->height()) / 2, ui->label_fl_hint->width(), ui->label_fl_hint->height()); } //保存人脸活体验证结果 void faceLiveness::onSaveFaceLiveVerifyResult(CBaseResponsePackage res) { try { if (res.nCode == 200) { m_nRetryCount = 0; if (m_pCloseTimer == nullptr) { m_pCloseTimer = std::make_shared(); m_pCloseTimer->setInterval(2000); connect(m_pCloseTimer.get(), &QTimer::timeout, this, [&]() { if (m_sLivenessStatus == STATUS_TYPE::ST_SUCCESS) { emit faceLivenessSucceed(); } else { emit faceLivenessFaild(); } }); } showVerifyResultUI(); m_pCloseTimer->start(); } else { if (res.sMessage.isEmpty()) { ShowMsg(QString::fromLocal8Bit("活体验证结果失败"), this, MSG_ICON_TYPE::mit_error); } else { ShowMsg(res.sMessage, this, MSG_ICON_TYPE::mit_error); } if(m_nRetryCount < 4) { saveLivenessResult(); m_nRetryCount++; } else { emit faceLivenessFaild(); } } } catch (const std::exception &e) { myDebug() << QString::fromLocal8Bit("人脸比对失败,%1").arg(e.what()); } } void faceLiveness::on_btn_fl_close_clicked() { emit faceLivenessFaild(); }