12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055 |
- #include "faceLiveness.h"
- #include "ui_faceLiveness.h"
- #include "CAppInfo.h"
- #include <QDesktopWidget>
- #include <QFile>
- #include <QFileInfo>
- #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>("CBaseResponsePackage");
- qRegisterMetaType<CClientExamProcessUploadSign>("CClientExamProcessUploadSign");
- qRegisterMetaType<CUploadFileToAliyun>("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<QTimer>();
- 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<int> 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<QTimer>();
- m_ActionTimer->setInterval(1000);
- connect(m_ActionTimer.get(), &QTimer::timeout, this, &faceLiveness::actionTimer);
- m_countdownTimer = std::make_shared<QTimer>();
- 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<QTimer>();
- m_initTimer->setInterval(100);
- connect(m_initTimer.get(), &QTimer::timeout, this, [&](){
- m_initTimer->stop();
- if(g_faceRecProcPtr == nullptr)
- {
- g_faceRecProcPtr = std::make_shared<CFaceRecProc>();
- }
- 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()<<QString::fromLocal8Bit("人脸比对失败,%1").arg(e.what());
- }
- }
- void faceLiveness::verifyAction(cv::Mat matImage)
- {
- try
- {
- bool bHasStatus = false;
- int nFaceCount = 0;
- float fScore = 0;
- if (m_currentVerifyInfo.bIsVerify || matImage.empty())
- {
- return;
- }
- m_currentVerifyInfo.matImage = matImage;
- if (m_currentVerifyInfo.sActionType == ACTION_TYPE::AT_FACE_DETECT)
- {
- SeetaRect rt;
- if (!g_faceRecProcPtr->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<CFaceRecProc>();
- }
- 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()<<QString("saveLivenessResult index of %1 matImage is empty").arg(i);
- if(m_livenessType == FACE_LIVENESS_TYPE::flt_entry_exam)
- {
- emit faceLivenessFaild();
- return;
- }
- }
- if (!m_livenessList[i].matImage.empty() &&
- m_livenessList[i].sUrl.isEmpty())
- {
- bSubmit = false;
- m_nCurIndex = i;
- m_currentVerifyInfo = m_livenessList[i];
- QString sImageFile = QString("temp/photo/%1.png").arg(CCommonTools::getUuid());
- QImage img = CCommonTools::Mat2QImage(m_currentVerifyInfo.matImage);
- img.save(sImageFile, "PNG");
- //上传图片
- CHttpRequestPackage hrp;
- hrp.sUri = "/api/ecs_oe_student/client/exam/process/upload/sign";
- hrp.nRequestType = RequestType::rtClientExamProcessUploadSign;
- hrp.sCommonStr = __FILE__;
- hrp.sCommonStr1 = sImageFile;
- hrp.sParamList.push_back(QString("fileSuffix,%1").arg(".png"));
- hrp.sParamList.push_back(QString("fileMd5,%1").arg(CCommonTools::fileMd5(sImageFile)));
- hrp.eParamType = HttpParamType::hptBody;
- g_httpBllPtr->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"<<e.what();
- }
- }
- void faceLiveness::onUploadFileToAliyun(CUploadFileToAliyun uploadFileToAliyun)
- {
- try
- {
- if(uploadFileToAliyun.sCommonStr == __FILE__)
- {
- if (uploadFileToAliyun.nCode == 200)
- {
- m_nRetryCount = 0;
- m_livenessList[m_nCurIndex].sUrl = uploadFileToAliyun.sFileUrl;
- if(m_livenessType == FACE_LIVENESS_TYPE::flt_entry_exam &&
- m_livenessList[m_nCurIndex].sActionType == ACTION_TYPE::AT_FACE_DETECT)
- {
- saveFaceCampareResult();
- }
- else
- {
- saveLivenessResult();
- }
- }
- else
- {
- if (uploadFileToAliyun.sMessage.isEmpty())
- {
- ShowMsg(QString::fromLocal8Bit("上传照片失败"), this, MSG_ICON_TYPE::mit_error);
- }
- else
- {
- ShowMsg(uploadFileToAliyun.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::saveFaceCampareResult()
- {
- CHttpRequestPackage hrp;
- hrp.sUri = "/api/ecs_oe_student/client/exam/process/saveFaceCompareResult";
- hrp.nRequestType = RequestType::rtSaveFaceCompareResult;
- Json::Value jBody = Json::Value::null;
- jBody["faceCompareResult"] = QString::number(m_livenessList[m_nCurIndex].fSimilarity).toStdString();
- jBody["fileUrl"] = m_livenessList[m_nCurIndex].sUrl.toStdString();
- jBody["pass"] = true;
- jBody["processTime"] = m_livenessList[m_nCurIndex].nEndTime - m_livenessList[m_nCurIndex].nStartTime;
- jBody["stranger"] = m_livenessList[m_nCurIndex].nFaceCount > 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"<<e.what();
- }
- }
- void faceLiveness::showVerifyResultUI()
- {
- if (m_sLivenessStatus == STATUS_TYPE::ST_SUCCESS)
- {
- ui->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<QTimer>();
- 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();
- }
|