OnlineResultHandler.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. #include "stdafx.h"
  2. #include "OnlineResultHandler.h"
  3. #include "OnlineCardIdentifor.h"
  4. #include "../EvaluationUtil/HttpClient.h"
  5. #include "ServerConfig.h"
  6. extern int g_my_scan_type;
  7. extern std::string g_strShoolID;
  8. extern int g_flagid;
  9. extern int g_schoolCardStatus;
  10. namespace OnLineCard{
  11. static CString AnsiToUnicode(const std::string& str)
  12. {
  13. CString strRet;
  14. int nLen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str.c_str(), -1, NULL, 0);
  15. if (nLen == 0){
  16. return strRet;
  17. }
  18. wchar_t* pResult = new wchar_t[nLen];
  19. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str.c_str(), -1, pResult, nLen);
  20. strRet = pResult;
  21. delete[]pResult;
  22. return strRet;
  23. }
  24. // unicode转ANSI
  25. std::string UnicodeToAnsi(const CString& str)
  26. {
  27. std::string ret;
  28. int nLen = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
  29. if (nLen == 0){
  30. return ret;
  31. }
  32. char* pResult = new char[nLen];
  33. WideCharToMultiByte(CP_ACP, 0, str, -1, pResult, nLen, NULL, NULL);
  34. ret = pResult;
  35. delete[] pResult;
  36. return ret;
  37. }
  38. COnlineResultHandler::COnlineResultHandler()
  39. {
  40. m_muban_page_count = 2;
  41. m_bOnlineCard = true;
  42. m_bUseQrCode = false;//是否使用二维码
  43. m_bIdentifyQrCode = false;// 是否识别二维码
  44. }
  45. COnlineResultHandler::~COnlineResultHandler()
  46. {
  47. }
  48. ServiceState COnlineResultHandler::OnStarting(void)
  49. {
  50. m_stop = FALSE;
  51. auto ret = __super::OnStarting();
  52. m_bOnlineCard = true;
  53. OnLineCard::PaperTemplate* pTmp = static_cast<OnLineCard::COnlineCardIdentifor*>(m_identifor)->GetTemplate();
  54. if (pTmp){
  55. m_bUseQrCode =pTmp->useQrCode;//是否使用二维码
  56. }
  57. m_bIdentifyQrCode = false;// 是否识别二维码
  58. return ret;
  59. }
  60. CString COnlineResultHandler::MarkHttpHeaderData()
  61. {
  62. TCHAR FilePath[MAX_PATH];
  63. GetModuleFileName(NULL, FilePath, MAX_PATH);
  64. CString ret;
  65. (_tcsrchr(FilePath, '\\'))[1] = 0;
  66. if (m_bErrorHandle){
  67. lstrcat(FilePath, _T("paperinfo.ini"));
  68. WCHAR JSESSIONID[512];
  69. GetPrivateProfileString(_T("paperinfo"), _T("session"), _T(""), JSESSIONID, 512, FilePath);
  70. ret = JSESSIONID;
  71. }
  72. else{
  73. lstrcat(FilePath, _T("config.ini"));
  74. #ifndef BACK_STAGE
  75. WCHAR SIG[512];
  76. GetPrivateProfileString(_T("SESSIONID"), _T("SIG"), _T(""), SIG, 512, FilePath);
  77. WCHAR TIME[512];
  78. GetPrivateProfileString(_T("SESSIONID"), _T("TIME"), _T(""), TIME, 512, FilePath);
  79. WCHAR ID[512];
  80. GetPrivateProfileString(L"SESSIONID", L"ID", L"", ID, 512, FilePath);
  81. WCHAR JSESSIONID[512];
  82. GetPrivateProfileString(_T("SESSIONID"), _T("JSESSIONID"), _T(""), JSESSIONID, 512, FilePath);
  83. ret.Format(_T("userid=%s&time=%s&sig=%s&session=%s"), ID, TIME, SIG, JSESSIONID);
  84. #else
  85. WCHAR MYCOOK[512];
  86. GetPrivateProfileString(_T("SESSIONID"), _T("MYCOOK"), _T(""), MYCOOK, 512, FilePath);
  87. CString ret;
  88. ret.Format(_T("%s"), MYCOOK);
  89. #endif
  90. }
  91. return ret;
  92. }
  93. int COnlineResultHandler::GetStudentInfo(CString paperIdStr, CString studentCard, int cardStatus, UnhandledPage& unhandled_page)
  94. {
  95. std::string response;
  96. CString postData;
  97. CString url;
  98. // 获取学生ID
  99. postData.Format(_T("paperIdStr=%s&studentCard=%s&cardStatus=%d"), paperIdStr, studentCard, cardStatus);
  100. url.Format(_T("%s/coachio/iointerface_v2/getStudentCard"), CServerConfig::server_url);
  101. CHttpClient httpClient;
  102. httpClient.SetSendHeader(MarkHttpHeaderData());
  103. httpClient.HttpPost(url, postData, response);
  104. Json::Features features;
  105. Json::Reader re(features);
  106. Json::Value root;
  107. re.parse(response, root);
  108. if (root["success"].isInt() && root["success"].asInt()){
  109. Json::Value object = root["object"];
  110. if (object["student_id"].isString()){
  111. unhandled_page.student_id = object["student_id"].asCString();
  112. }
  113. }
  114. return 0;
  115. }
  116. ServiceState COnlineResultHandler::OnRunning(void)
  117. {
  118. CIdentifyTask* task = taskManager->getCurrentHandleTask();
  119. if (task){
  120. pUnhandledPageInfo = task->getUnhandledPageManager();
  121. pUnhandledPageInfo->bOnlineCard = true;
  122. pUnhandledPageInfo->nSubjectID = 0;
  123. OnLineCard::PaperTemplate* pTmp = static_cast<OnLineCard::COnlineCardIdentifor*>(m_identifor)->GetTemplate();
  124. if (pTmp){
  125. pUnhandledPageInfo->nSubjectID = pTmp->subject_id;
  126. }
  127. }else{
  128. return stoping;
  129. }
  130. m_muban_page_count = m_identifor->GetMubanCount();
  131. UnhandledPageInfo& unhandledPageInfo = *pUnhandledPageInfo;
  132. int handle_count_limit = (m_stop&&unhandledPageInfo.unhandled_page_count > 0) ? min(m_muban_page_count, unhandledPageInfo.unhandled_page_count) : m_muban_page_count;
  133. if (unhandledPageInfo.unhandled_page_count >= handle_count_limit){
  134. if (m_muban_page_count > 0){
  135. try{
  136. LOGI("SAVE_PAPER_BEGIN");
  137. SavePaper(handle_count_limit);
  138. LOGI("SAVE_PAPER_END");
  139. }
  140. catch (cv::Exception&e){
  141. for (int m = 0; m < m_muban_page_count; m++)
  142. {
  143. int page_index = (unhandledPageInfo.first_unhandled_page_index + m) % MAX_UNHANDLED_PAGE;
  144. if (pUnhandledPageInfo->bOnlineCard){
  145. static_cast<OnLineCard::COnlineCardIdentifor*>(m_identifor)->FreeResult(unhandledPageInfo.unhandled_pages[page_index].omr_result);
  146. }
  147. else{
  148. unhandledPageInfo.result->FreeResult(unhandledPageInfo.unhandled_pages[page_index].omr_result);
  149. }
  150. }
  151. unhandledPageInfo.first_unhandled_page_index = (unhandledPageInfo.first_unhandled_page_index + m_muban_page_count) % MAX_UNHANDLED_PAGE;
  152. unhandledPageInfo.unhandled_page_count -= m_muban_page_count;
  153. // printf("SavePaper 异常:%s\n", e.what());
  154. }
  155. }
  156. }
  157. OMR_RESULT * omr_result = static_cast<COnlineCardIdentifor*>(m_identifor)->GetResult(TRUE);
  158. if (omr_result == NULL){
  159. if (unhandledPageInfo.unhandled_page_count <= 0){
  160. return stoping;
  161. }
  162. m_stop = TRUE;
  163. return running;
  164. }
  165. LOGI("OnLineCardSavePage-BEGIN");
  166. OnLineCardSavePage(omr_result);
  167. m_bSvePage = true;
  168. LOGI("OnLineCardSavePage-END");
  169. return running;
  170. }
  171. //保存识别的结果到待处理存储区
  172. int COnlineResultHandler::OnLineCardSavePage(OMR_RESULT * omr_result)
  173. {
  174. UnhandledPageInfo & unhandledPageInfo = *pUnhandledPageInfo;
  175. int index = (unhandledPageInfo.first_unhandled_page_index + unhandledPageInfo.unhandled_page_count) % MAX_UNHANDLED_PAGE;
  176. unhandledPageInfo.unhandled_page_count++;
  177. UnhandledPage& unhandled_page = unhandledPageInfo.unhandled_pages[index];
  178. unhandled_page.identified = omr_result->identified;
  179. int page_index = unhandled_page.page_index = omr_result->card_index;
  180. unhandled_page.omr_result = omr_result;
  181. unhandled_page.student_code = "";
  182. unhandled_page.student_id = "";
  183. // 学生ID
  184. if (omr_result->identified && omr_result->qr_result.size() == 1 ){
  185. bool bGetStuInfo = true;
  186. if (omr_result->qr_result[0].is_stu_id){
  187. g_flagid = 1;
  188. unhandled_page.student_id = omr_result->qr_result[0].qr_str;
  189. //unhandled_page.student_code = unhandled_page.student_id;
  190. }
  191. else{
  192. unhandled_page.student_code = omr_result->qr_result[0].qr_str;
  193. g_flagid = 0;
  194. if (m_bUseQr){
  195. std::vector<std::string> split_qr;
  196. split(m_strQr, (std::string)",", &split_qr);
  197. if (split_qr.size() >= 3){
  198. std::vector<std::string> _vct;
  199. split(split_qr[2], std::string("@"), &_vct);
  200. // std::to_string(m_examId) + "," + std::to_string(paper_id) + (student_code.empty() ? "" : ("," + student_code));
  201. if (_vct.size() >= 3){
  202. bGetStuInfo = false;
  203. unhandled_page.student_id = _vct[2];
  204. g_flagid = 1;
  205. }
  206. }
  207. }
  208. }
  209. if (bGetStuInfo){
  210. /*
  211. CString tmp = AnsiToUnicode(unhandled_page.student_code);
  212. GetStudentInfo(AnsiToUnicode(unhandled_page.omr_result->online_card_paperid),
  213. tmp,
  214. unhandled_page.omr_result->schoolCardStatus, unhandled_page);
  215. */
  216. g_schoolCardStatus = unhandled_page.omr_result->schoolCardStatus;
  217. }
  218. }
  219. return 0;
  220. }
  221. #define DIV 20
  222. static bool sort_line_by_x(const CvPoint* p1, CvPoint* p2)
  223. {
  224. return p1[0].x < p2[0].x;
  225. }
  226. static bool sort_line_by_y(const CvPoint* p1, CvPoint* p2)
  227. {
  228. return p1[0].y > p2[0].y;
  229. }
  230. void COnlineResultHandler::cutImage(IplImage* img, string strQuestionNo)
  231. {
  232. IplImage* src = cvCreateImage(cvGetSize(img), 8, 1);
  233. IplImage* dst1 = cvCreateImage(cvGetSize(src), 8, 1);
  234. IplImage* dst = cvCreateImage(cvGetSize(src), 8, 1);
  235. cvCvtColor(img, src, CV_BGR2GRAY);
  236. CvMemStorage* storage = cvCreateMemStorage(0);
  237. CvSeq* lines = 0;
  238. cvCanny(src, dst1, 50, 150, 3);
  239. lines = cvHoughLines2(dst1, storage, CV_HOUGH_PROBABILISTIC, 0.5, 0.5*CV_PI / 180, 20, 20, 3);
  240. vector<CvPoint*> pVec;
  241. vector<CvPoint*> pyVec;
  242. int iCnt = 0, iCntY = 0;
  243. for (int i = 0; i < lines->total; i++)
  244. {
  245. CvPoint* line = (CvPoint*)cvGetSeqElem(lines, i);
  246. if (abs(line[0].x - line[1].x)<200) continue;
  247. if (abs(line[0].y - line[1].y)>5) continue;
  248. if (abs(line[0].y - src->height)<5) continue;
  249. if (abs(line[1].y - src->height)<5) continue;
  250. pVec.push_back(line);
  251. iCnt++;
  252. }
  253. for (int i = 0; i < lines->total; i++)
  254. {
  255. CvPoint* line = (CvPoint*)cvGetSeqElem(lines, i);
  256. if (abs(line[0].y - line[1].y)<200) continue;
  257. if (abs(line[0].x - line[1].x)>5) continue;
  258. pyVec.push_back(line);
  259. iCntY++;
  260. }
  261. if (pyVec.size()>1)
  262. {
  263. sort(pyVec.begin(), pyVec.end(), sort_line_by_x);//x坐标从小到大顺序排列
  264. }
  265. if (pVec.size()>1)
  266. {
  267. sort(pVec.begin(), pVec.end(), sort_line_by_y);
  268. }
  269. CvPoint* lineTx = NULL;
  270. int OriginX, OriginY;
  271. if (pyVec.size()>1 && pVec.size()>1)
  272. {
  273. vector<CvPoint*>::iterator itx = pyVec.end() - 1;
  274. int len1 = pyVec.size();
  275. for (lineTx = *itx; (lineTx[0].x>src->width / 2) && (len1>0);)
  276. {
  277. len1--;
  278. if (len1>0)
  279. {
  280. itx--;
  281. lineTx = *itx;
  282. }
  283. }
  284. OriginX = lineTx[0].x + 20;
  285. CvPoint* lineTy = NULL;
  286. vector<CvPoint*>::iterator it = pVec.begin();
  287. for (lineTy = *it; (lineTy[0].y>src->height / 2) && (it != pVec.end());)
  288. {
  289. it++;
  290. if (it != pVec.end())
  291. lineTy = *it;
  292. }
  293. OriginY = lineTy[0].y + 50;
  294. }
  295. if (pVec.size()>1)
  296. {
  297. CvPoint* line = *(pVec.begin());
  298. CvPoint* firstLine = *(pVec.end() - 1);
  299. int width;
  300. width = abs(line[0].x - line[1].x) - 200;
  301. int height = line[0].y - firstLine[0].y;
  302. if (width<src->width * 2 / 3)
  303. {
  304. width = src->width - 300;
  305. }
  306. int x = line[0].x<line[1].x ? line[0].x : line[1].x;
  307. x = x + 50;
  308. if (x>src->width / 20)
  309. x = src->width / 20 + 50;
  310. int y;
  311. if (height<src->height * 2 / 3)
  312. {
  313. height = src->height - 10;
  314. y = height;
  315. }
  316. else
  317. y = line[0].y;
  318. int iHeight = height / DIV;
  319. int cnt = 0;
  320. CvRect rc;
  321. CvRect rcS;
  322. cvThreshold(dst1, dst, 128, 255, CV_THRESH_BINARY_INV);
  323. for (int i = 1; i <= DIV; i++)
  324. {
  325. rc = cvRect(x, y - iHeight*i, width, iHeight);
  326. if (i == 1)
  327. rc.height -= 5;
  328. cnt++;
  329. int TotalNumberOfPixels = rc.width * rc.height;
  330. if (rc.width >= 0 && rc.height >= 0 && ((rc.x + rc.width)<dst->width) && ((rc.y + rc.height)<dst->height))
  331. {
  332. cvSetImageROI(dst, rc);
  333. int iPix = TotalNumberOfPixels - cvCountNonZero(dst);//计算黑色像素数量
  334. cvResetImageROI(dst);
  335. if (iPix<30)
  336. rcS = rc;
  337. else
  338. {
  339. rcS = rc;
  340. break;
  341. }
  342. }
  343. }
  344. if (pyVec.size()>1)
  345. {
  346. CvRect rcOnlyTitle;
  347. rcOnlyTitle.x = OriginX;
  348. rcOnlyTitle.y = OriginY;
  349. rcOnlyTitle.width = rc.width;
  350. CvPoint* lineT = *(pVec.begin());
  351. rcOnlyTitle.height = abs(lineT[0].y - OriginY - 20);
  352. if (rcOnlyTitle.height>0)
  353. {
  354. if (rcOnlyTitle.width >= 0 && rcOnlyTitle.height >= 0 && ((rcOnlyTitle.x + rcOnlyTitle.width)<dst->width) && ((rcOnlyTitle.y + rcOnlyTitle.height)<dst->height))
  355. {
  356. cvSetImageROI(dst, rcOnlyTitle);
  357. int TotalNumberOfPixels2 = rcOnlyTitle.width * rcOnlyTitle.height;
  358. int iPix2 = TotalNumberOfPixels2 - cvCountNonZero(dst);//计算黑色像素数量
  359. cvResetImageROI(dst);
  360. if (iPix2<20)
  361. {
  362. int iQuestionNo = atoi(strQuestionNo.c_str());
  363. }
  364. }
  365. }
  366. }
  367. CvRect rcR = cvRect(0, 0, dst->width, rcS.y + iHeight + 30);//rsult
  368. if ((rcR.y + rcR.height)<dst->height)
  369. cvSetImageROI(img, rcR);
  370. }
  371. cvReleaseMemStorage(&storage);
  372. cvReleaseImage(&src);//释放img所指向的内存空间
  373. cvReleaseImage(&dst1);
  374. cvReleaseImage(&dst);
  375. }
  376. void COnlineResultHandler::SaveImages(vector<CUT_AREA_RESULT*> &area_results, CMemZipFile &zip,
  377. int subjectID, BOOL bOnlineCard, char *strPaperCode, const std::vector<std::string> &postMarkTypeIDVec,
  378. std::map<std::string, int> &vecTwoPic)
  379. {
  380. // printf("SaveImages-begin\n");
  381. //return __super::SaveImages(area_results, zip, strPaperCode, postMarkTypeIDVec, vecTwoPic);
  382. std::string area_name;
  383. BOOL flag = false;
  384. if (bOnlineCard && subjectID == 0)
  385. {
  386. for (int i = 0; i < postMarkTypeIDVec.size(); i++)
  387. {
  388. for (int j = 0; j < area_results.size(); j++){
  389. if (postMarkTypeIDVec[i] == area_results[j]->area_name)
  390. {
  391. flag = true;
  392. break;
  393. }
  394. }
  395. }
  396. }
  397. if (area_results[0]->area_name == "")
  398. {
  399. area_name = area_results[0]->area_name;
  400. int idx;
  401. area_name = ((idx = area_name.find('.')) < 0) ? area_name : area_name.substr(0, idx);
  402. CString question_code;
  403. question_code.Format(_T("%s.jpg"), CString(area_name.c_str()));
  404. zip.PutNextEntry(question_code);
  405. }
  406. else
  407. {
  408. area_name = area_results[0]->area_name;
  409. CString question_code;
  410. question_code.Format(_T("%s.jpg"), CString(area_name.c_str()));
  411. zip.PutNextEntry(question_code);
  412. }
  413. if (area_results.size() > 1 && area_results[0]->is_cut > 0){
  414. int width = 0;
  415. int height = 0;
  416. for (int jj = 0; jj<area_results.size(); jj++)
  417. {
  418. if (area_results[jj]->width>width)width = area_results[jj]->width;
  419. height += area_results[jj]->height;
  420. }
  421. cv::Mat img_big(cv::Size(width, height), CV_8UC3,cv::Scalar(255,255,255));
  422. for (int ii = 0, top = 0; ii < area_results.size(); ii++)
  423. {
  424. Mat ff = Mat(1, area_results[ii]->img_data.size(), CV_8U, area_results[ii]->img_data.data());
  425. Mat temp_img = imdecode(ff, CV_LOAD_IMAGE_COLOR);
  426. cv::Rect rc_tmp(0, top, temp_img.cols, temp_img.rows);
  427. Mat cut = img_big(rc_tmp);
  428. temp_img.copyTo(cut);
  429. top += temp_img.rows;
  430. }
  431. //////////////////////////////////////////////////////////////////////////
  432. vector<uchar> dst;
  433. //cv::Mat _img = cv::cvarrToMat(img);
  434. vector<int> compression_params;
  435. compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
  436. compression_params.push_back(25);
  437. imencode(".jpg", img_big, dst, compression_params);
  438. //cvResetImageROI(img);
  439. zip.Write(&dst[0], dst.size());
  440. if (!(bOnlineCard && subjectID != 0) && area_results[0]->is_cut == 1)
  441. {
  442. CString question_code;
  443. question_code.Format(_T("%sf.jpg"), CString(area_name.c_str()));
  444. zip.PutNextEntry(question_code);
  445. zip.Write(&dst[0], dst.size());
  446. }
  447. }
  448. else
  449. {
  450. if (area_results[0]->is_cut > 0)
  451. {
  452. zip.Write(area_results[0]->img_data.data(), area_results[0]->img_data.size());
  453. if (!(bOnlineCard && subjectID != 0))
  454. {
  455. zip.PutNextEntry(AnsiToUnicode(area_name + "f.jpg"));
  456. zip.Write(area_results[0]->img_data.data(), area_results[0]->img_data.size());
  457. }
  458. }
  459. else
  460. zip.Write(area_results[0]->img_data.data(), area_results[0]->img_data.size());
  461. }
  462. if (flag && area_results.size() > 1 && area_results[0]->is_cut > 0){
  463. vector<int> compression_params_low;
  464. compression_params_low.push_back(CV_IMWRITE_JPEG_QUALITY);
  465. compression_params_low.push_back(40);
  466. vector<int> compression_params_high;
  467. compression_params_high.push_back(CV_IMWRITE_JPEG_QUALITY);
  468. compression_params_high.push_back(60);
  469. for (int jj = 0; jj < area_results.size(); jj++)
  470. {
  471. CString question_code;
  472. question_code.Format(_T("%s_%d.jpg"), CString(area_results[0]->area_name.c_str()), jj + 1);
  473. zip.PutNextEntry(question_code);
  474. int width = area_results[jj]->width;
  475. int height = area_results[jj]->height;
  476. IplImage* img = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
  477. cvSet(img, cvScalarAll(255));
  478. Mat ff = Mat(1, area_results[jj]->img_data.size(), CV_8U, area_results[jj]->img_data.data());
  479. Mat temp_img = imdecode(ff, CV_LOAD_IMAGE_GRAYSCALE);
  480. cvSetImageROI(img, cvRect(0, 0, temp_img.cols, temp_img.rows));
  481. cvCopy(&IplImage(temp_img), img);
  482. cvResetImageROI(img);
  483. char sz_question_code[520] = { 0 };
  484. WideCharToMultiByte(CP_ACP, 0, question_code, -1, sz_question_code, 520, NULL, NULL);
  485. vector<uchar> dst;
  486. cv::Mat _img = cv::cvarrToMat(img);
  487. if (img->height > 500){
  488. imencode(".jpg", _img, dst, compression_params_low);
  489. }
  490. else{
  491. imencode(".jpg", _img, dst, compression_params_high);
  492. }
  493. cvReleaseImage(&img);
  494. zip.Write(&dst[0], dst.size());
  495. }
  496. vecTwoPic[area_results[0]->area_name.c_str()] = area_results.size();
  497. }
  498. }
  499. }