inprogressFace.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. #include "inprogressFace.h"
  2. #include "logproc.h"
  3. #include "CCommonTools.h"
  4. #include "CFaceRecProc.h"
  5. #include "CAppInfo.h"
  6. #include "json/json.h"
  7. #include <QFileInfo>
  8. std::shared_ptr<CInprogressFace> g_inProcessFace = nullptr;
  9. CInprogressFace::CInprogressFace()
  10. {
  11. qRegisterMetaType<CClientExamProcessUploadSign>("CClientExamProcessUploadSign");
  12. connect(g_httpBllPtr.get(), &CHttpBll::sgnClientExamProcessUploadSign, this, &CInprogressFace::onClientExamProcessUploadSign);
  13. qRegisterMetaType<CBaseResponsePackage>("CBaseResponsePackage");
  14. connect(g_httpBllPtr.get(), &CHttpBll::sgnSaveFaceCaptureResult, this, &CInprogressFace::onSaveFaceCaptureResult);
  15. qRegisterMetaType<CUploadFileToAliyun>("CUploadFileToAliyun");
  16. connect(g_httpBllPtr.get(), &CHttpBll::sgnUploadFileToAliyun, this, &CInprogressFace::onUploadFileToAliyun);
  17. genCameraInfo();
  18. m_bIsRun = true;
  19. m_thread = std::thread(std::bind(&CInprogressFace::threadProc, this));
  20. }
  21. void CInprogressFace::genCameraInfo()
  22. {
  23. std::vector<CameraInfo> list;
  24. if(CCommonTools::listCameraDevices(list) <= 0)
  25. {
  26. return;
  27. }
  28. Json::Value jCameraInfo;
  29. for(CameraInfo &ci : list)
  30. {
  31. if(ci.pid.empty() || ci.vid.empty())
  32. {
  33. m_bHasVirtualCamera = true;
  34. }
  35. Json::Value jCamera;
  36. jCamera["detail"] = QString::fromStdWString(ci.detail.c_str()).toStdString();
  37. jCamera["name"] = QString::fromStdWString(ci.name.c_str()).toStdString();
  38. jCamera["pid"] = QString::fromStdWString(ci.pid.c_str()).toStdString();
  39. jCamera["vid"] = QString::fromStdWString(ci.vid.c_str()).toStdString();
  40. jCameraInfo.append(jCamera);
  41. }
  42. m_sCameraInfo = Json::FastWriter().write(jCameraInfo).c_str();
  43. }
  44. CInprogressFace::~CInprogressFace()
  45. {
  46. m_bIsRun = false;
  47. m_thread.join();
  48. }
  49. void CInprogressFace::startFaceVerify(bool bVerify)
  50. {
  51. m_bStart = bVerify;
  52. }
  53. void CInprogressFace::addImage(cv::Mat matImage)
  54. {
  55. if(m_bStart)
  56. {
  57. std::scoped_lock lock(m_mImgList);
  58. m_vImgList.push_back(matImage);
  59. }
  60. }
  61. void CInprogressFace::addFaceCountImage(cv::Mat matImage)
  62. {
  63. myServerLog()<<"inprogress start"<<m_bStart;
  64. if(m_bStart)
  65. {
  66. std::scoped_lock lock(m_mImgFaceCountList);
  67. m_vImgFaceCountList.push_back(matImage);
  68. }
  69. }
  70. void CInprogressFace::threadProc()
  71. {
  72. if (g_faceRecProcPtr == nullptr)
  73. {
  74. g_faceRecProcPtr = std::make_shared<CFaceRecProc>();
  75. }
  76. if (!g_appInfoPtr->m_sStudentPhotoPath.isEmpty())
  77. {
  78. QString sFileName = g_appInfoPtr->m_sStudentPhotoPath.right(g_appInfoPtr->m_sStudentPhotoPath.length() - g_appInfoPtr->m_sStudentPhotoPath.lastIndexOf("/") - 1);
  79. sFileName = g_appInfoPtr->m_sCacheFileDir + sFileName;
  80. if (!QFile::exists(sFileName))
  81. {
  82. emit compareFailed(QString::fromLocal8Bit("底照下载失败,请检查网络"));
  83. return;
  84. }
  85. if(!g_faceRecProcPtr->setBaseImage(sFileName))
  86. {
  87. emit compareFailed(g_faceRecProcPtr->errorMsg());
  88. return;
  89. }
  90. }
  91. else
  92. {
  93. emit compareFailed(QString::fromLocal8Bit("当前考试未底照"));
  94. return;
  95. }
  96. while(m_bIsRun)
  97. {
  98. if(m_bStart)
  99. {
  100. if(m_vImgFaceCountList.begin() != m_vImgFaceCountList.end())
  101. {
  102. cv::Mat matImage;
  103. {
  104. std::scoped_lock lock(m_mImgFaceCountList);
  105. matImage = (*m_vImgFaceCountList.begin()).clone();
  106. m_vImgFaceCountList.erase(m_vImgFaceCountList.begin());
  107. }
  108. if(matImage.empty())
  109. {
  110. myServerLog()<<"Inprogress matImage.empty";
  111. continue;
  112. }
  113. int nFaceCount = 0;
  114. if(g_faceRecProcPtr->getFaceCount(matImage, nFaceCount))
  115. {
  116. if(nFaceCount == 0)
  117. {
  118. //无人脸
  119. emit compareFailed(QString::fromLocal8Bit("请调整坐姿,诚信考试"));
  120. }
  121. else if(nFaceCount > 1 && g_appInfoPtr->m_oExamInfo.bIsStrangerEnable)
  122. {
  123. //陌生人
  124. emit compareFailed(QString::fromLocal8Bit("请独立完成考试"));
  125. }
  126. }
  127. else
  128. {
  129. QString sErrorMsg = g_faceRecProcPtr->errorMsg();
  130. myDebug()<<QString::fromLocal8Bit("人脸检测失败:")<<sErrorMsg;
  131. }
  132. }
  133. if(m_vImgList.begin() != m_vImgList.end())
  134. {
  135. cv::Mat matImage;
  136. {
  137. std::scoped_lock lock(m_mImgList);
  138. matImage = (*m_vImgList.begin()).clone();
  139. m_vImgList.erase(m_vImgList.begin());
  140. }
  141. if(matImage.empty())
  142. {
  143. myServerLog()<<"matImage.empty";
  144. continue;
  145. }
  146. int nFaceCount = 0;
  147. float fScore = 0;
  148. bool bRealness = false;
  149. int nTime = 0;
  150. if(!g_faceRecProcPtr->getMaxFaceScoreWithBase(matImage.clone(), nFaceCount, fScore, bRealness, nTime))
  151. {
  152. //比对失败
  153. QString sErrorMsg = g_faceRecProcPtr->errorMsg();
  154. myDebug()<<QString::fromLocal8Bit("人脸检测失败:")<<sErrorMsg;
  155. uploadFile(matImage.clone(), nFaceCount, fScore, bRealness);
  156. emit compareFailed(sErrorMsg);
  157. }
  158. else
  159. {
  160. if(nFaceCount == 0)
  161. {
  162. //无人脸
  163. uploadFile(matImage.clone(), nFaceCount, fScore, bRealness);
  164. emit compareFailed(QString::fromLocal8Bit("请让我看到您的正脸"));
  165. }
  166. else if(nFaceCount > 1 && g_appInfoPtr->m_oExamInfo.bIsStrangerEnable)
  167. {
  168. //陌生人
  169. uploadFile(matImage.clone(), nFaceCount, fScore, bRealness);
  170. emit compareFailed(QString::fromLocal8Bit("检测到陌生人"));
  171. }
  172. else
  173. {
  174. uploadFile(matImage.clone(), nFaceCount, fScore, bRealness);
  175. }
  176. }
  177. }
  178. }
  179. else
  180. {
  181. Sleep(100);
  182. }
  183. }
  184. }
  185. void CInprogressFace::uploadFile(cv::Mat faceMat, int nFaceCount, float fScore, int nRealness)
  186. {
  187. QString sFileName = QString("temp/photo/%1.png").arg(CCommonTools::getUuid());
  188. QImage imgCompare = CCommonTools::Mat2QImage(faceMat);
  189. if(imgCompare.isNull() || !imgCompare.save(sFileName, "PNG"))
  190. {
  191. myServerLog()<<"imgCompare is null:"<<imgCompare.isNull();
  192. try
  193. {
  194. QFileInfo file(sFileName);
  195. cv::imwrite(file.absoluteFilePath().toStdString(), faceMat);
  196. }
  197. catch (std::exception &e)
  198. {
  199. emit reAddImage();
  200. myServerLog()<<"cv::imwrite failed reAddImage";
  201. return;
  202. }
  203. }
  204. QFile file(sFileName);
  205. if(!file.exists())
  206. {
  207. emit reAddImage();
  208. myServerLog()<<sFileName<<" is not exists reAddImage";
  209. return;
  210. }
  211. if(!file.open(QIODevice::ReadOnly))
  212. {
  213. emit reAddImage();
  214. myServerLog()<<"open file failed reAddImage";
  215. return;
  216. }
  217. if(file.size() < 1024)
  218. {
  219. emit reAddImage();
  220. myServerLog()<<"reAddImage, filesize < 1kb";
  221. return;
  222. }
  223. CHttpRequestPackage hrp;
  224. hrp.sUri = "/api/ecs_oe_student/client/exam/process/upload/sign";
  225. hrp.nRetryCount = 10;
  226. hrp.nRequestType = RequestType::rtClientExamProcessUploadSign;
  227. hrp.sParamList.push_back(QString("fileSuffix,%1").arg(".png"));
  228. hrp.sParamList.push_back(QString("fileMd5,%1").arg(CCommonTools::fileMd5(sFileName)));
  229. hrp.sCommonStr = QString("%1,%2,%3,%4").arg(__FILE__).arg(nFaceCount).arg(fScore).arg(nRealness);
  230. hrp.sCommonStr1 = sFileName;
  231. hrp.eParamType = HttpParamType::hptBody;
  232. g_httpBllPtr->post(hrp);
  233. }
  234. //文件上传
  235. void CInprogressFace::onClientExamProcessUploadSign(CClientExamProcessUploadSign processUpload)
  236. {
  237. QStringList list = processUpload.sCommonStr.split(",");
  238. if(list.count() == 4)
  239. {
  240. QString sFile = list[0];
  241. int nFaceCount = list[1].toInt();
  242. float fScore = list[2].toFloat();
  243. int nRealness = list[3].toInt();
  244. if(__FILE__ == sFile)
  245. {
  246. if (processUpload.nCode == 200)
  247. {
  248. CHttpRequestPackage hrp;
  249. hrp.nRetryCount = 10;
  250. hrp.sUri = processUpload.sFormUrl;
  251. hrp.nRequestType = RequestType::rtUploadFileToAliyun;
  252. hrp.sCommonStr = QString("%1,%2,%3,%4").arg(__FILE__).arg(nFaceCount).arg(fScore).arg(nRealness);;
  253. hrp.sCommonStr1 = processUpload.sAccessUrl;
  254. hrp.sParamList.push_back(QString("OSSAccessKeyId,%1").arg(processUpload.sOssAcessKeyId));
  255. hrp.sParamList.push_back(QString("Signature,%1").arg(processUpload.sSignature));
  256. hrp.sParamList.push_back(QString("key,%1").arg(processUpload.sKey));
  257. hrp.sParamList.push_back(QString("policy,%1").arg(processUpload.sPolicy));
  258. hrp.sParamList.push_back(QString("success_action_status,%1").arg(200));
  259. hrp.sParamList.push_back(QString("formdataFileType,file,%1").arg(processUpload.sFilePath));
  260. hrp.bNoHostPrefix = true;
  261. hrp.eParamType = HttpParamType::hptFormdata;
  262. g_httpBllPtr->post(hrp);
  263. }
  264. else
  265. {
  266. emit reAddImage();
  267. }
  268. }
  269. }
  270. }
  271. void CInprogressFace::onUploadFileToAliyun(CUploadFileToAliyun uploadFileToAliyun)
  272. {
  273. QStringList list = uploadFileToAliyun.sCommonStr.split(",");
  274. if(list.count() == 4)
  275. {
  276. QString sFile = list[0];
  277. int nFaceCount = list[1].toInt();
  278. float fScore = list[2].toFloat();
  279. int nRealness = list[3].toInt();
  280. if(__FILE__ == sFile)
  281. {
  282. if (uploadFileToAliyun.nCode == 200)
  283. {
  284. CHttpRequestPackage hrp;
  285. hrp.nRetryCount = 10;
  286. hrp.sUri = "/api/ecs_oe_student/client/exam/process/saveFaceCaptureResult";
  287. hrp.nRequestType = RequestType::rtSaveFaceCaptureResult;
  288. Json::Value jBody = Json::Value::null;
  289. jBody["examRecordDataId"] = g_appInfoPtr->m_oExamInfo.nExamRecordDataId;
  290. jBody["faceCompareResult"] = fScore;
  291. jBody["facelivenessResult"] = nRealness;
  292. jBody["fileUrl"] = uploadFileToAliyun.sFileUrl.toStdString();
  293. jBody["pass"] = (fScore * 100 > g_appInfoPtr->m_oExamInfo.nFaceThreshold) ? true : false;
  294. jBody["stranger"] = nFaceCount > 1;
  295. jBody["hasVirtualCamera"] = m_bHasVirtualCamera;
  296. jBody["cameraInfos"] = m_sCameraInfo.toStdString();
  297. hrp.sParamList.push_back(QString("CustomBody,%1").arg(jBody.toStyledString().c_str()));
  298. hrp.eParamType = HttpParamType::hptCustomBody;
  299. myServerLog() << jBody.toStyledString().c_str();
  300. g_httpBllPtr->post(hrp);
  301. }
  302. else
  303. {
  304. emit reAddImage();
  305. }
  306. }
  307. }
  308. }
  309. //保存人脸抓拍比对验证结果
  310. void CInprogressFace::onSaveFaceCaptureResult(CBaseResponsePackage res)
  311. {
  312. if(res.nCode == 200)
  313. {
  314. }
  315. else
  316. {
  317. emit reAddImage();
  318. }
  319. }