faceCompare.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. #include "faceCompare.h"
  2. #include "ui_faceCompare.h"
  3. #include "CAppInfo.h"
  4. #include <QDesktopWidget>
  5. #include <QFile>
  6. #include <QFileInfo>
  7. #include "awMsgBox.h"
  8. #include "logproc.h"
  9. #include "CCommonTools.h"
  10. #include "CFaceRecProc.h"
  11. faceCompare::faceCompare(QWidget *parent) :
  12. QWidget(parent),
  13. ui(new Ui::faceCompare)
  14. {
  15. ui->setupUi(this);
  16. setStyleSheet(g_appInfoPtr->m_sQssStr);
  17. initUI();
  18. m_bStartCompare = false;
  19. qRegisterMetaType<CBaseResponsePackage>("CBaseResponsePackage");
  20. qRegisterMetaType<CProcessUpload>("CProcessUpload");
  21. connect(g_httpBllPtr.get(), &CHttpBll::sgnProcessUpload, this, &faceCompare::onProcessUpload);
  22. connect(g_httpBllPtr.get(), &CHttpBll::sgnSaveFaceCompareResult, this, &faceCompare::onSaveFaceCompareResult);
  23. QString sFileName = g_appInfoPtr->m_sStudentPhotoPath.right(g_appInfoPtr->m_sStudentPhotoPath.length() - g_appInfoPtr->m_sStudentPhotoPath.lastIndexOf("/") - 1);
  24. sFileName = g_appInfoPtr->m_sCacheFileDir + sFileName;
  25. if(!QFile::exists(sFileName))
  26. {
  27. CHttpRequestPackage hrp;
  28. hrp.sUri = g_appInfoPtr->m_sStudentPhotoPath;
  29. hrp.sCommonStr = sFileName;
  30. hrp.sCommonStr1 = __FILE__;
  31. hrp.nRequestType = RequestType::rtDownLoadFile;
  32. hrp.nRetryCount = 3;
  33. g_httpBllPtr->downLoad(hrp);
  34. }
  35. m_pVideoTimer = std::make_shared<QTimer>();
  36. m_pVideoTimer->setInterval(200);
  37. connect(m_pVideoTimer.get(), &QTimer::timeout, this, [&](){
  38. std::scoped_lock lock(m_imageMutex);
  39. QImage img = CCommonTools::Mat2QImage(m_nCurImage);
  40. ui->widget_fc_camera->setAutoFillBackground(true);
  41. QPalette palette;
  42. palette.setBrush(QPalette::Window, QBrush(img.scaled(ui->widget_fc_camera->width(), ui->widget_fc_camera->height())));
  43. ui->widget_fc_camera->setPalette(palette);
  44. });
  45. g_clientVideoProcPtr->startTest(this);
  46. m_pVideoTimer->start();
  47. connect(this, &faceCompare::compareFailed, this, [&](QString sErrorMsg) {
  48. ShowMsg(sErrorMsg, this, MSG_ICON_TYPE::mit_error);
  49. ui->btn_fc_compare->setEnabled(true);
  50. });
  51. m_bIsRun = true;
  52. m_thread = std::thread(std::bind(&faceCompare::threadProc, this));
  53. }
  54. faceCompare::~faceCompare()
  55. {
  56. m_pVideoTimer->stop();
  57. g_clientVideoProcPtr->stopTest();
  58. m_bIsRun = false;
  59. m_thread.join();
  60. awMsgBox::clear(this);
  61. delete ui;
  62. }
  63. void faceCompare::onRenderVideoFrame(const char* userId, TRTCVideoStreamType streamType, TRTCVideoFrame* frame)
  64. {
  65. if(g_clientVideoProcPtr->isCameraTest())
  66. {
  67. __int64 nServerTime = g_appInfoPtr->serverMTime();
  68. if(nServerTime - m_lastFaceTime >= 100)
  69. {
  70. m_lastFaceTime = nServerTime;
  71. cv::Mat matImg;
  72. cv::cvtColor(cv::Mat(frame->height, frame->width, CV_8UC4, frame->data), matImg, CV_RGBA2RGB);
  73. std::scoped_lock lock(m_imageMutex);
  74. m_nCurImage = matImg.clone();
  75. }
  76. }
  77. }
  78. void faceCompare::onDownLoadFile(CDownLoadFileInfo downLoadFileInfo)
  79. {
  80. if(downLoadFileInfo.sModuleName == __FILE__)
  81. {
  82. if (downLoadFileInfo.nCode == 200)
  83. {
  84. QString sFileName = g_appInfoPtr->m_sStudentPhotoPath.right(g_appInfoPtr->m_sStudentPhotoPath.length() - g_appInfoPtr->m_sStudentPhotoPath.lastIndexOf("/") - 1);
  85. sFileName = g_appInfoPtr->m_sCacheFileDir + sFileName;
  86. ui->label_fc_basePhoto->setPixmap(QPixmap(sFileName).scaled(ui->label_fc_basePhoto->width(), ui->label_fc_basePhoto->height(),
  87. Qt::IgnoreAspectRatio));
  88. }
  89. else
  90. {
  91. if(downLoadFileInfo.sMessage.isEmpty())
  92. {
  93. ShowMsg(QString::fromLocal8Bit("下载失败"), this, MSG_ICON_TYPE::mit_error);
  94. }
  95. else
  96. {
  97. ShowMsg(downLoadFileInfo.sMessage, this, MSG_ICON_TYPE::mit_error);
  98. }
  99. }
  100. }
  101. }
  102. void faceCompare::initUI()
  103. {
  104. QDesktopWidget *dekwiget = QApplication::desktop();
  105. setGeometry(0, 0, dekwiget->width(), dekwiget->height());
  106. ui->widget_mask->setGeometry(0, 0, dekwiget->width(), dekwiget->height());
  107. ui->widget_fc_BG->setGeometry((width() - g_appInfoPtr->m_fRate*800)/2, (height() - g_appInfoPtr->m_fRate*536)/2,
  108. g_appInfoPtr->m_fRate*800, g_appInfoPtr->m_fRate*536);
  109. ui->label_fc_title->adjustSize();
  110. ui->label_fc_title->setGeometry(g_appInfoPtr->m_fRate*20, g_appInfoPtr->m_fRate*16,
  111. ui->label_fc_title->width(), ui->label_fc_title->height());
  112. ui->btn_fc_close->setGeometry(ui->widget_fc_BG->width() - g_appInfoPtr->m_fRate*(20 + 16),
  113. g_appInfoPtr->m_fRate*16, g_appInfoPtr->m_fRate*16, g_appInfoPtr->m_fRate*16);
  114. ui->label_HLine->setGeometry(0, ui->label_fc_title->y() + ui->label_fc_title->height() + g_appInfoPtr->m_fRate*16,
  115. ui->widget_fc_BG->width(), g_appInfoPtr->m_fRate*1 < 1 ? 1 : g_appInfoPtr->m_fRate*1);
  116. ui->label_fc_basePhoto->setGeometry(g_appInfoPtr->m_fRate*30, ui->label_HLine->y() + ui->label_HLine->height() + g_appInfoPtr->m_fRate*20,
  117. g_appInfoPtr->m_fRate*140, g_appInfoPtr->m_fRate*180);
  118. QString sFileName = g_appInfoPtr->m_sStudentPhotoPath.right(g_appInfoPtr->m_sStudentPhotoPath.length() - g_appInfoPtr->m_sStudentPhotoPath.lastIndexOf("/") - 1);
  119. sFileName = g_appInfoPtr->m_sCacheFileDir + sFileName;
  120. ui->label_fc_basePhoto->setPixmap(QPixmap(sFileName).scaled(ui->label_fc_basePhoto->width(), ui->label_fc_basePhoto->height(),
  121. Qt::IgnoreAspectRatio));
  122. ui->label_fc_basePhotoTips->setGeometry(ui->label_fc_basePhoto->x() + g_appInfoPtr->m_fRate*10,
  123. ui->label_fc_basePhoto->y() + ui->label_fc_basePhoto->height() - g_appInfoPtr->m_fRate*(10+20),
  124. ui->label_fc_basePhoto->width() - g_appInfoPtr->m_fRate*10*2, g_appInfoPtr->m_fRate*20);
  125. ui->widget_fc_camera->setGeometry(ui->label_fc_basePhoto->x() + ui->label_fc_basePhoto->width() + g_appInfoPtr->m_fRate*20,
  126. ui->label_fc_basePhoto->y(), g_appInfoPtr->m_fRate*580, g_appInfoPtr->m_fRate*300);
  127. ui->btn_fc_compare->setGeometry((ui->widget_fc_camera->width() - g_appInfoPtr->m_fRate*120)/2,
  128. ui->widget_fc_camera->height() - g_appInfoPtr->m_fRate*(20 + 40),
  129. g_appInfoPtr->m_fRate*120, g_appInfoPtr->m_fRate*40);
  130. ui->label_fc_tips->adjustSize();
  131. ui->label_fc_tips->setGeometry(ui->widget_fc_camera->x(), ui->widget_fc_camera->y() + ui->widget_fc_camera->height() + g_appInfoPtr->m_fRate*20,
  132. ui->label_fc_tips->width(), ui->label_fc_tips->height());
  133. ui->label_fc_note->setGeometry(ui->widget_fc_camera->x(), ui->label_fc_tips->y() + ui->label_fc_tips->height() + g_appInfoPtr->m_fRate*5,
  134. g_appInfoPtr->m_fRate*580, g_appInfoPtr->m_fRate*100);
  135. }
  136. void faceCompare::on_btn_fc_compare_clicked()
  137. {
  138. if(g_faceRecProcPtr == nullptr)
  139. {
  140. g_faceRecProcPtr = std::make_shared<CFaceRecProc>();
  141. if (!g_appInfoPtr->m_sStudentPhotoPath.isEmpty())
  142. {
  143. QString sFileName = g_appInfoPtr->m_sStudentPhotoPath.right(g_appInfoPtr->m_sStudentPhotoPath.length() - g_appInfoPtr->m_sStudentPhotoPath.lastIndexOf("/") - 1);
  144. sFileName = g_appInfoPtr->m_sCacheFileDir + sFileName;
  145. if(!QFile::exists(sFileName))
  146. {
  147. ShowMsg(QString::fromLocal8Bit("底照下载失败,请检查网络"), this, MSG_ICON_TYPE::mit_error);
  148. return;
  149. }
  150. QFileInfo filePath(sFileName);
  151. if(!g_faceRecProcPtr->setBaseImage(filePath.absoluteFilePath()))
  152. {
  153. ShowMsg(g_faceRecProcPtr->errorMsg(), this, MSG_ICON_TYPE::mit_error);
  154. return;
  155. }
  156. }
  157. else
  158. {
  159. ShowMsg(QString::fromLocal8Bit("本场考试需要进行人脸检测,但是您没有上传底照,请联系老师"), this, MSG_ICON_TYPE::mit_error);
  160. QTimer::singleShot(3000, this, [&]() { emit exitFaceCompare(); });
  161. return;
  162. }
  163. }
  164. m_bStartCompare = true;
  165. ui->btn_fc_compare->setEnabled(false);
  166. }
  167. void faceCompare::on_btn_fc_close_clicked()
  168. {
  169. m_bIsRun = false;
  170. emit exitFaceCompare();
  171. }
  172. void faceCompare::threadProc()
  173. {
  174. while(m_bIsRun)
  175. {
  176. if(m_bStartCompare)
  177. {
  178. cv::Mat img = m_nCurImage;
  179. if(!img.empty())
  180. {
  181. //人脸比对
  182. int nFaceCount = 0;
  183. float fScore = 0;
  184. bool bRealness = false;
  185. int nTime = 0;
  186. if(!g_faceRecProcPtr->getMaxFaceScoreWithBase(img, nFaceCount, fScore, bRealness, nTime))
  187. {
  188. //比对失败
  189. QString sErrorMsg = g_faceRecProcPtr->errorMsg();
  190. emit compareFailed(sErrorMsg);
  191. }
  192. else
  193. {
  194. if(nFaceCount == 0)
  195. {
  196. //无人脸
  197. emit compareFailed(QString::fromLocal8Bit("请让我看到您的正脸"));
  198. }
  199. else if(nFaceCount > 1 && g_appInfoPtr->m_oExamInfo.bIsStrangerEnable)
  200. {
  201. //陌生人
  202. emit compareFailed(QString::fromLocal8Bit("检测到陌生人"));
  203. }
  204. else
  205. {
  206. #ifdef _DEBUG
  207. g_appInfoPtr->m_oExamInfo.nWarnThreshold = 1;
  208. #endif // _DEBUG
  209. if(fScore*100 > g_appInfoPtr->m_oExamInfo.nWarnThreshold)
  210. {
  211. m_fScore = fScore;
  212. m_nFaceCount = nFaceCount;
  213. m_nTime = nTime;
  214. //比对成功
  215. QString sFileName = QString("temp/photo/%1.png").arg(CCommonTools::getUuid());
  216. QImage imgCompare = CCommonTools::Mat2QImage(img);
  217. imgCompare.save(sFileName, "PNG");
  218. CHttpRequestPackage hrp;
  219. hrp.sUri = "/api/ecs_oe_student/client/exam/process/upload";
  220. hrp.nRequestType = RequestType::rtProcessUpload;
  221. hrp.sCommonStr = __FILE__;
  222. hrp.sParamList.push_back(QString("formdataFileType,file,%1").arg(sFileName));
  223. hrp.sParamList.push_back(QString("md5,%1").arg(CCommonTools::fileMd5(sFileName)));
  224. hrp.eParamType = HttpParamType::hptFormdata;
  225. g_httpBllPtr->post(hrp);
  226. }
  227. else
  228. {
  229. //低于阈值
  230. emit compareFailed(QString::fromLocal8Bit("检测失败"));
  231. }
  232. }
  233. }
  234. m_bStartCompare = false;
  235. }
  236. }
  237. else
  238. {
  239. Sleep(100);
  240. }
  241. }
  242. }
  243. //文件上传
  244. void faceCompare::onProcessUpload(CProcessUpload processUpload)
  245. {
  246. if(processUpload.sCommonStr == __FILE__)
  247. {
  248. if(processUpload.nCode == 200)
  249. {
  250. CHttpRequestPackage hrp;
  251. hrp.sUri = "/api/ecs_oe_student/client/exam/process/saveFaceCompareResult";
  252. hrp.nRequestType = RequestType::rtSaveFaceCompareResult;
  253. Json::Value jBody = Json::Value::null;
  254. jBody["faceCompareResult"] = QString::number(m_fScore).toStdString();
  255. jBody["fileUrl"] = processUpload.sFileUrl.toStdString();
  256. jBody["pass"] = true;
  257. jBody["processTime"] = m_nTime;
  258. jBody["stranger"] = m_nFaceCount > 1;
  259. hrp.sParamList.push_back(QString("CustomBody,%1").arg(jBody.toStyledString().c_str()));
  260. hrp.eParamType = HttpParamType::hptCustomBody;
  261. g_httpBllPtr->post(hrp);
  262. }
  263. else
  264. {
  265. if(processUpload.sMessage.isEmpty())
  266. {
  267. ShowMsg(QString::fromLocal8Bit("上传照片失败"), this, MSG_ICON_TYPE::mit_error);
  268. }
  269. else
  270. {
  271. ShowMsg(processUpload.sMessage, this, MSG_ICON_TYPE::mit_error);
  272. }
  273. }
  274. }
  275. }
  276. //保存人脸识别比对验证结果
  277. void faceCompare::onSaveFaceCompareResult(CBaseResponsePackage res)
  278. {
  279. if(res.nCode == 200)
  280. {
  281. ShowMsg(QString::fromLocal8Bit("人脸比对成功"), this, MSG_ICON_TYPE::mit_succeed);
  282. QTimer::singleShot(3000, this, [&](){
  283. emit faceComparePass();
  284. });
  285. }
  286. else
  287. {
  288. if(res.sMessage.isEmpty())
  289. {
  290. ShowMsg(QString::fromLocal8Bit("保存人脸识别信息失败"), this, MSG_ICON_TYPE::mit_error);
  291. }
  292. else
  293. {
  294. ShowMsg(res.sMessage, this, MSG_ICON_TYPE::mit_error);
  295. }
  296. }
  297. }