|
@@ -7,6 +7,8 @@
|
|
|
#include "jsoncpp/json.h"
|
|
|
#include "curl/curl.h"
|
|
|
#include "zbar.h"
|
|
|
+#include <thread>
|
|
|
+#include <future>
|
|
|
|
|
|
extern "C" {
|
|
|
using namespace std;
|
|
@@ -74,6 +76,63 @@ string ZbarDecoder(Mat img, int & nAnchorsToQrCode)
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+bool cpmpareFileName(string & a, string & b)
|
|
|
+{
|
|
|
+ if(a.length() != b.length())
|
|
|
+ return a.length() < b.length();
|
|
|
+ int nRet = strcmp(a.c_str(), b.c_str());
|
|
|
+ return nRet < 0;
|
|
|
+}
|
|
|
+
|
|
|
+string getQrcode(Mat tImg, int nX, int nY)
|
|
|
+{
|
|
|
+ string strRet = "";
|
|
|
+ if(tImg.empty())
|
|
|
+ return strRet;
|
|
|
+ Mat roiMat = tImg(Rect(nX, nY, tImg.cols / 4, tImg.rows / 5));
|
|
|
+ Mat imgGray;
|
|
|
+ cvtColor(roiMat, imgGray, CV_BGR2GRAY); // 灰度化
|
|
|
+ erode(imgGray, imgGray, Mat()); //图片腐蚀,缩小高亮(白色)区域
|
|
|
+ int nAnchorsToQrCode = 0;
|
|
|
+ strRet = ZbarDecoder(imgGray, nAnchorsToQrCode);
|
|
|
+ return strRet;
|
|
|
+}
|
|
|
+
|
|
|
+void findQrcode(string & strPath, string & strRet)
|
|
|
+{
|
|
|
+// // 开始时间点
|
|
|
+// auto start = std::chrono::high_resolution_clock::now();
|
|
|
+ Mat tImg = imread(strPath);
|
|
|
+ vector<shared_future<string>> tFutures;
|
|
|
+ shared_future<string> tFut1 = std::async(launch::async, getQrcode, tImg, 0, 0);
|
|
|
+ shared_future<string> tFut2 = std::async(launch::async, getQrcode, tImg, tImg.cols * 3 / 4, 0);
|
|
|
+ shared_future<string> tFut3 = std::async(launch::async, getQrcode, tImg, tImg.cols * 3 / 4, tImg.rows * 4 / 5);
|
|
|
+ shared_future<string> tFut4 = std::async(launch::async, getQrcode, tImg, 0, tImg.rows * 4 / 5);
|
|
|
+ tFutures.emplace_back(tFut1);
|
|
|
+ tFutures.emplace_back(tFut2);
|
|
|
+ tFutures.emplace_back(tFut3);
|
|
|
+ tFutures.emplace_back(tFut4);
|
|
|
+// int nFinishedCount = 0;
|
|
|
+// while(nFinishedCount < 4)
|
|
|
+// {
|
|
|
+// nFinishedCount = 0;
|
|
|
+// for(int i = 0; i < tFutures.size(); i++)
|
|
|
+// if(tFutures[i].wait_for(chrono::microseconds(100)) == future_status::ready)
|
|
|
+// nFinishedCount++;
|
|
|
+// }
|
|
|
+ for(int i = 0; i < tFutures.size(); i++)
|
|
|
+ {
|
|
|
+ tFutures[i].wait();
|
|
|
+ strRet += tFutures[i].get();
|
|
|
+ if(!strRet.empty())
|
|
|
+ break;
|
|
|
+ }
|
|
|
+// auto finish = std::chrono::high_resolution_clock::now();
|
|
|
+// // 计算时间差,即执行时间
|
|
|
+// chrono::duration<double> elapsed = finish - start;
|
|
|
+// auto deltaTime = elapsed.count();
|
|
|
+}
|
|
|
+
|
|
|
paperPreIdentify::paperPreIdentify(int nSchoolId)
|
|
|
{
|
|
|
m_nSchoolId = nSchoolId;
|
|
@@ -91,13 +150,13 @@ PAPERIDENTIFYSTATUS paperPreIdentify::scanPaper(string strImgDir, string strIp)
|
|
|
m_vPaperPath.clear();
|
|
|
m_abnPaperMap.clear();
|
|
|
traverseDir(strImgDir);
|
|
|
- sort(m_vPaperPath.begin(), m_vPaperPath.end());
|
|
|
+ sort(m_vPaperPath.begin(), m_vPaperPath.end(), cpmpareFileName);
|
|
|
return preIdentify(m_vPaperPath, strIp);
|
|
|
}
|
|
|
|
|
|
PAPERIDENTIFYSTATUS paperPreIdentify::scanPaper(std::vector<std::string> papersVec, string strIp)
|
|
|
{
|
|
|
- sort(papersVec.begin(), papersVec.end());
|
|
|
+ sort(papersVec.begin(), papersVec.end(), cpmpareFileName);
|
|
|
return preIdentify(papersVec, strIp);
|
|
|
}
|
|
|
|
|
@@ -117,6 +176,23 @@ bool paperPreIdentify::findAnchors(PaperPage sPage)
|
|
|
|
|
|
string paperPreIdentify::readQrCode(PaperPage sPage)
|
|
|
{
|
|
|
+ string strPath = "";
|
|
|
+ string strRet = "";
|
|
|
+// auto start = std::chrono::high_resolution_clock::now();
|
|
|
+
|
|
|
+ for(int i = 0; i < 2; i++)
|
|
|
+ {
|
|
|
+ strPath = i == 0 ? sPage.firstPage : sPage.secondPage;
|
|
|
+ findQrcode(strPath, strRet);
|
|
|
+ if(!strRet.empty())
|
|
|
+ break;
|
|
|
+ }
|
|
|
+// auto finish = std::chrono::high_resolution_clock::now();
|
|
|
+// // 计算时间差,即执行时间
|
|
|
+// chrono::duration<double> elapsed = finish - start;
|
|
|
+// auto deltaTime = elapsed.count();
|
|
|
+ return strRet;
|
|
|
+#if 0
|
|
|
string strRet;
|
|
|
for (int i = 0; i < 2; i++)
|
|
|
{
|
|
@@ -154,6 +230,7 @@ string paperPreIdentify::readQrCode(PaperPage sPage)
|
|
|
break;
|
|
|
}
|
|
|
return strRet;
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
void paperPreIdentify::traverseDir(string strImgDir)
|
|
@@ -557,16 +634,53 @@ int paperPreIdentify::getBalckAreaCount(Mat& tMat)
|
|
|
}
|
|
|
|
|
|
PAPERIDENTIFYSTATUS paperPreIdentify::preIdentify(vector<string>& papersVec, string strIp) {
|
|
|
- vector<PaperPage> tAllPaperList;
|
|
|
int nPaperSize = papersVec.size();
|
|
|
if(0 == nPaperSize || nPaperSize % 2 != 0)
|
|
|
return PAPERNUMODD;
|
|
|
|
|
|
- int nGetTmpFailCount = 0;
|
|
|
- int nGetQrcodeFailCount = 0;
|
|
|
+ nGetTmpFailCount = 0;
|
|
|
+ nGetQrcodeFailCount = 0;
|
|
|
+ qrCodeCountMap.clear();
|
|
|
+ qrCodeContentMap.clear();
|
|
|
+ tAllPaperList.clear();
|
|
|
+ int nMid = nPaperSize / 2;
|
|
|
+ if(nPaperSize > 10)
|
|
|
+ {
|
|
|
+ nMid = nPaperSize > 20 ? nMid : 10;
|
|
|
+ auto func1 = bind(&paperPreIdentify::identifyPaper, this, 0, nMid, strIp, papersVec);
|
|
|
+ auto func2 = bind(&paperPreIdentify::identifyPaper, this, nMid, nPaperSize, strIp, papersVec);
|
|
|
+ shared_future<int> tFut1 = async(launch::async, func1);
|
|
|
+ shared_future<int> tFut2 = async(launch::async, func2);
|
|
|
+ vector<shared_future<int>> tFutures;
|
|
|
+ tFutures.emplace_back(tFut1);
|
|
|
+ tFutures.emplace_back(tFut2);
|
|
|
+ for(int i = 0; i < 2; i++)
|
|
|
+ tFutures[i].wait();
|
|
|
+ int nRet1 = 3, nRet2 = 3;
|
|
|
+ try{
|
|
|
+ nRet1 = tFut1.get();
|
|
|
+ nRet2 = tFut2.get();
|
|
|
+ }
|
|
|
+ catch (const exception & e) {
|
|
|
+ string strErr = e.what();
|
|
|
+ int i = 0;
|
|
|
+ }
|
|
|
+ if(nRet1 != FINISHPREIDENTIFY)
|
|
|
+ return (PAPERIDENTIFYSTATUS)nRet1;
|
|
|
+ if(nRet2 != FINISHPREIDENTIFY)
|
|
|
+ return (PAPERIDENTIFYSTATUS)nRet2;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ auto func1 = bind(&paperPreIdentify::identifyPaper, this, 0, nPaperSize, strIp, papersVec);
|
|
|
+ shared_future<int> tFut1 = async(launch::async, func1);
|
|
|
+ tFut1.wait();
|
|
|
+ int nRet = tFut1.get();
|
|
|
+ if(nRet != FINISHPREIDENTIFY)
|
|
|
+ return (PAPERIDENTIFYSTATUS)nRet;
|
|
|
+ }
|
|
|
+#if 0
|
|
|
string strFirPagePath;
|
|
|
- map<string, int> qrCodeCountMap;
|
|
|
- map<string, int> qrCodeContentMap;
|
|
|
for(int i = 0; i < nPaperSize; i++)
|
|
|
{
|
|
|
if(i % 2 == 0)
|
|
@@ -622,7 +736,8 @@ PAPERIDENTIFYSTATUS paperPreIdentify::preIdentify(vector<string>& papersVec, str
|
|
|
//仅记录能够成功获取模板信息的QrCode
|
|
|
if(qrCodeCountMap.size() == 0)
|
|
|
qrCodeCountMap[strQRCode] = 2;
|
|
|
- qrCodeCountMap[strQRCode] = 1;
|
|
|
+ else
|
|
|
+ qrCodeCountMap[strQRCode] = 1;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
@@ -641,6 +756,7 @@ PAPERIDENTIFYSTATUS paperPreIdentify::preIdentify(vector<string>& papersVec, str
|
|
|
tAllPaperList.push_back(tPage);
|
|
|
}
|
|
|
}
|
|
|
+#endif
|
|
|
auto iter = qrCodeCountMap.begin();
|
|
|
int nMaxCount;
|
|
|
string strMaxCountQr = "";
|
|
@@ -682,6 +798,81 @@ PAPERIDENTIFYSTATUS paperPreIdentify::preIdentify(vector<string>& papersVec, str
|
|
|
return FINISHPREIDENTIFY;
|
|
|
}
|
|
|
|
|
|
+int paperPreIdentify::identifyPaper(int nBegin, int nEnd, string strIp, vector<string>& papersVec)
|
|
|
+{
|
|
|
+ string strFirPagePath;
|
|
|
+ for(int i = nBegin; i < nEnd; i++)
|
|
|
+ {
|
|
|
+ if(i % 2 == 0)
|
|
|
+ {
|
|
|
+ strFirPagePath = papersVec.at(i);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ PaperPage tPage;
|
|
|
+ tPage.firstPage = strFirPagePath;
|
|
|
+ tPage.secondPage = papersVec.at(i);
|
|
|
+ string strQRCode = readQrCode(tPage);
|
|
|
+ if(strQRCode.empty())
|
|
|
+ {
|
|
|
+ //获取模板失败答题卡计数
|
|
|
+ if(i + 1 <= 10)
|
|
|
+ nGetQrcodeFailCount++;
|
|
|
+ if(nGetQrcodeFailCount == 5 && nEnd >= 10 || nGetQrcodeFailCount == nEnd / 2)
|
|
|
+ return GETQRCODEFAILED;
|
|
|
+ //当扫描的这一批答题卡同时存在二维码无法识别和二维码无法找到模板信息时,弹窗提示二维码找不到模板信息
|
|
|
+ if(nGetTmpFailCount + nGetQrcodeFailCount == 5 && nEnd >= 10 || nGetTmpFailCount + nGetQrcodeFailCount == nEnd / 2)
|
|
|
+ return GETTEMPLATEFAILED;
|
|
|
+ tPage.ePaperStatus = PAPER_CANNOTREADQRCODE;
|
|
|
+ tAllPaperList.push_back(tPage);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ else if(i + 1 <= 10)
|
|
|
+ qrCodeContentMap[strQRCode] = 1;
|
|
|
+ tPage.qrCode = strQRCode;
|
|
|
|
|
|
+ //前五份之内存在如果存在试卷夹带,中止扫描
|
|
|
+ if(i + 1 <= 10 && qrCodeContentMap.size() > 1)
|
|
|
+ return PAPERDOPING;
|
|
|
+
|
|
|
+ if(qrCodeCountMap.count(strQRCode) == 0)
|
|
|
+ {
|
|
|
+ //二维码能正确识别则根据识别出的答题卡ID获取模板信息
|
|
|
+ bool bGetTempSucceful = getCardTemplate(strQRCode, strIp);
|
|
|
+ if(!bGetTempSucceful)
|
|
|
+ {
|
|
|
+ //获取模板失败答题卡计数
|
|
|
+ if(i + 1 <= 10)
|
|
|
+ nGetTmpFailCount++;
|
|
|
+ //当扫描的这一批答题卡同时存在二维码无法识别和二维码无法找到模板信息时,弹窗提示二维码找不到模板信息
|
|
|
+ if(nGetTmpFailCount + nGetQrcodeFailCount == 5 && nEnd >= 10 || nGetTmpFailCount + nGetQrcodeFailCount == nEnd / 2)
|
|
|
+ return GETTEMPLATEFAILED;
|
|
|
+ tPage.ePaperStatus = PAPER_INVALIDQRCODE;
|
|
|
+ tAllPaperList.push_back(tPage);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if(nBegin == 0)
|
|
|
+ {
|
|
|
+ //仅记录能够成功获取模板信息的QrCode
|
|
|
+ if(qrCodeCountMap.size() == 0)
|
|
|
+ qrCodeCountMap[strQRCode] = 2;
|
|
|
+ else
|
|
|
+ qrCodeCountMap[strQRCode] = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //计数加1
|
|
|
+ if(nBegin == 0 && qrCodeCountMap.size() == 1)
|
|
|
+ qrCodeCountMap[strQRCode]++;
|
|
|
+ }
|
|
|
+ tAllPaperList.push_back(tPage);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return FINISHPREIDENTIFY;
|
|
|
+}
|
|
|
|
|
|
|