CvxText.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. #include "pch.h"
  2. #include "CvxText.h"
  3. #include <json/json.h>
  4. #include "BaseUtility.h"
  5. using namespace std;
  6. using namespace cv;
  7. #if defined(GNUC)
  8. #pragma GCC diagnostic push
  9. #pragma GCC diagnostic ignored “-Wdeprecated-declarations”
  10. #elif defined(_MSC_VER)
  11. #pragma warning(disable : 4996)
  12. #endif
  13. void GetStringSize(HDC hDC, const char* str, int* w, int* h)
  14. {
  15. SIZE size;
  16. GetTextExtentPoint32A(hDC, str, strlen(str), &size);
  17. if (w != 0) *w = size.cx;
  18. if (h != 0) *h = size.cy;
  19. }
  20. cv::Size GetTextSize(const char* str, int fontSize, const char* fn, bool italic, bool underline)
  21. {
  22. HDC hDC = CreateCompatibleDC(0);
  23. LOGFONTA lf;
  24. lf.lfHeight = -fontSize;
  25. lf.lfWidth = 0;
  26. lf.lfEscapement = 0;
  27. lf.lfOrientation = 0;
  28. lf.lfWeight = 5;
  29. lf.lfItalic = italic; //斜体
  30. lf.lfUnderline = underline; //下划线
  31. lf.lfStrikeOut = 0;
  32. lf.lfCharSet = DEFAULT_CHARSET;
  33. lf.lfOutPrecision = 0;
  34. lf.lfClipPrecision = 0;
  35. lf.lfQuality = PROOF_QUALITY;
  36. lf.lfPitchAndFamily = 0;
  37. strcpy_s(lf.lfFaceName, fn);
  38. HFONT hf = CreateFontIndirectA(&lf);
  39. HFONT hOldFont = (HFONT)SelectObject(hDC, hf);
  40. int strBaseW = 0, strBaseH = 0;
  41. int singleRow = 0;
  42. char buf[1 << 12];
  43. strcpy_s(buf, str);
  44. char *bufT[1 << 12]; // 这个用于分隔字符串后剩余的字符,可能会超出。
  45. //处理多行
  46. {
  47. int nnh = 0;
  48. int cw, ch;
  49. const char* ln = strtok_s(buf, "\n", bufT);
  50. while (ln != 0)
  51. {
  52. GetStringSize(hDC, ln, &cw, &ch);
  53. strBaseW = max(strBaseW, cw);
  54. strBaseH = max(strBaseH, ch);
  55. ln = strtok_s(0, "\n", bufT);
  56. nnh++;
  57. }
  58. singleRow = strBaseH;
  59. strBaseH *= nnh;
  60. }
  61. SelectObject(hDC, hOldFont);
  62. DeleteObject(hf);
  63. DeleteDC(hDC);
  64. cv::Size size;
  65. size.width = strBaseW;
  66. size.height = strBaseH;
  67. return size;
  68. }
  69. void putTextZH(cv::Mat &dst, cv::Size & rSize, const char* str, Point org, Scalar color, int fontSize, const char* fn, bool italic, bool underline)
  70. {
  71. CV_Assert(dst.data != 0 && (dst.channels() == 1 || dst.channels() == 3));
  72. int x, y, r, b;
  73. if (org.x > dst.cols || org.y > dst.rows) return;
  74. x = org.x < 0 ? -org.x : 0;
  75. y = org.y < 0 ? -org.y : 0;
  76. LOGFONTA lf;
  77. lf.lfHeight = -fontSize;
  78. lf.lfWidth = 0;
  79. lf.lfEscapement = 0;
  80. lf.lfOrientation = 0;
  81. lf.lfWeight = 5;
  82. lf.lfItalic = italic; //斜体
  83. lf.lfUnderline = underline; //下划线
  84. lf.lfStrikeOut = 0;
  85. lf.lfCharSet = DEFAULT_CHARSET;
  86. lf.lfOutPrecision = 0;
  87. lf.lfClipPrecision = 0;
  88. lf.lfQuality = PROOF_QUALITY;
  89. lf.lfPitchAndFamily = 0;
  90. strcpy_s(lf.lfFaceName, fn);
  91. HFONT hf = CreateFontIndirectA(&lf);
  92. HDC hDC = CreateCompatibleDC(0);
  93. HFONT hOldFont = (HFONT)SelectObject(hDC, hf);
  94. int strBaseW = 0, strBaseH = 0;
  95. int singleRow = 0;
  96. char buf[1 << 12];
  97. strcpy_s(buf, str);
  98. char *bufT[1 << 12]; // 这个用于分隔字符串后剩余的字符,可能会超出。
  99. //处理多行
  100. {
  101. int nnh = 0;
  102. int cw, ch;
  103. const char* ln = strtok_s(buf, "\n", bufT);
  104. while (ln != 0)
  105. {
  106. GetStringSize(hDC, ln, &cw, &ch);
  107. strBaseW = max(strBaseW, cw);
  108. strBaseH = max(strBaseH, ch);
  109. ln = strtok_s(0, "\n", bufT);
  110. nnh++;
  111. }
  112. singleRow = strBaseH;
  113. strBaseH *= nnh;
  114. }
  115. rSize.width = strBaseW;
  116. rSize.height = strBaseH;
  117. if (org.x + strBaseW < 0 || org.y + strBaseH < 0)
  118. {
  119. SelectObject(hDC, hOldFont);
  120. DeleteObject(hf);
  121. DeleteObject(hDC);
  122. return;
  123. }
  124. r = org.x + strBaseW > dst.cols ? dst.cols - org.x - 1 : strBaseW - 1;
  125. b = org.y + strBaseH > dst.rows ? dst.rows - org.y - 1 : strBaseH - 1;
  126. org.x = org.x < 0 ? 0 : org.x;
  127. org.y = org.y < 0 ? 0 : org.y;
  128. BITMAPINFO bmp = { 0 };
  129. BITMAPINFOHEADER& bih = bmp.bmiHeader;
  130. int strDrawLineStep = strBaseW * 3 % 4 == 0 ? strBaseW * 3 : (strBaseW * 3 + 4 - ((strBaseW * 3) % 4));
  131. bih.biSize = sizeof(BITMAPINFOHEADER);
  132. bih.biWidth = strBaseW;
  133. bih.biHeight = strBaseH;
  134. bih.biPlanes = 1;
  135. bih.biBitCount = 24;
  136. bih.biCompression = BI_RGB;
  137. bih.biSizeImage = strBaseH * strDrawLineStep;
  138. bih.biClrUsed = 0;
  139. bih.biClrImportant = 0;
  140. void* pDibData = 0;
  141. HBITMAP hBmp = CreateDIBSection(hDC, &bmp, DIB_RGB_COLORS, &pDibData, 0, 0);
  142. CV_Assert(pDibData != 0);
  143. HBITMAP hOldBmp = (HBITMAP)SelectObject(hDC, hBmp);
  144. //color.val[2], color.val[1], color.val[0]
  145. SetTextColor(hDC, RGB(255, 255, 255));
  146. SetBkColor(hDC, 0);
  147. //SetStretchBltMode(hDC, COLORONCOLOR);
  148. strcpy_s(buf, str);
  149. const char* ln = strtok_s(buf, "\n", bufT);
  150. int outTextY = 0;
  151. while (ln != 0)
  152. {
  153. TextOutA(hDC, 0, outTextY, ln, strlen(ln));
  154. outTextY += singleRow;
  155. ln = strtok_s(0, "\n", bufT);
  156. }
  157. uchar* dstData = (uchar*)dst.data;
  158. int dstStep = dst.step / sizeof(dstData[0]);
  159. unsigned char* pImg = (unsigned char*)dst.data + org.x * dst.channels() + org.y * dstStep;
  160. unsigned char* pStr = (unsigned char*)pDibData + x * 3;
  161. for (int tty = y; tty <= b; ++tty)
  162. {
  163. unsigned char* subImg = pImg + (tty - y) * dstStep;
  164. unsigned char* subStr = pStr + (strBaseH - tty - 1) * strDrawLineStep;
  165. for (int ttx = x; ttx <= r; ++ttx)
  166. {
  167. for (int n = 0; n < dst.channels(); ++n) {
  168. double vtxt = subStr[n] / 255.0;
  169. int cvv = vtxt * color.val[n] + (1 - vtxt) * subImg[n];
  170. subImg[n] = cvv > 255 ? 255 : (cvv < 0 ? 0 : cvv);
  171. }
  172. subStr += 3;
  173. subImg += dst.channels();
  174. }
  175. }
  176. SelectObject(hDC, hOldBmp);
  177. SelectObject(hDC, hOldFont);
  178. DeleteObject(hf);
  179. DeleteObject(hBmp);
  180. DeleteDC(hDC);
  181. }
  182. ///////////////////////////// 数据收集卡 ///////////////////////////////////////
  183. // 获取字符串的画布上的宽度
  184. int getLineStrWidth(string str, int fontSize, int ttBoxW, int tiSl, int backPix) {
  185. int iw = str.length()*fontSize*0.5;
  186. iw += ttBoxW;
  187. iw += tiSl;
  188. iw += backPix;
  189. iw += fontSize * 1.5; // 题号的宽度 最多不超过1.5个字体宽度 56.
  190. return iw;
  191. }
  192. // 转码 utf-8 2 ansi
  193. static void UTF82ANSI(LPCSTR lpBuff, int nLen, char* pData, int iMaxLen)
  194. {
  195. ZeroMemory(pData, sizeof(char)*iMaxLen);
  196. int nCont = MultiByteToWideChar(CP_UTF8, 0, lpBuff, nLen, NULL, 0);
  197. WCHAR* szTemp = new WCHAR[nCont + 1];
  198. ZeroMemory(szTemp, sizeof(WCHAR)*(nCont + 1));
  199. MultiByteToWideChar(CP_UTF8, 0, lpBuff, nLen, szTemp, nCont);
  200. //获取缓冲区大小,并申请空间,缓冲区大小事按字节计算的
  201. int len = WideCharToMultiByte(CP_ACP, 0, szTemp, nCont, NULL, 0, NULL, NULL);
  202. if (len < iMaxLen) {
  203. WideCharToMultiByte(CP_ACP, 0, szTemp, nCont, pData, len, NULL, NULL);
  204. }
  205. else {
  206. char* buffer = new char[len + 1];
  207. //宽字节编码转换成多字节编码
  208. WideCharToMultiByte(CP_ACP, 0, szTemp, nCont, buffer, len, NULL, NULL);
  209. buffer[len] = '\0';
  210. //删除缓冲区并返回值
  211. strncpy(pData, buffer, iMaxLen - 1);
  212. delete[] buffer;
  213. buffer = NULL;
  214. }
  215. delete[]szTemp;
  216. szTemp = NULL;
  217. }
  218. // 二进制码生成获取
  219. void createBinString(Mat & img, int pageNum, int ptw, int pth, cv::Point ptStart, vector<cv::Rect>& vecBoxPages) {
  220. vector<int> vecBinStr; vecBinStr.resize(12);
  221. for (size_t i = 11; i > 0; i--) {
  222. int ys = pageNum % 2;
  223. vecBinStr[i] = ys;
  224. pageNum = pageNum / 2;
  225. }
  226. vecBoxPages.clear();
  227. int ptPgW = ptw / 2; int ptPgH = pth / 2;
  228. for (int j = 0; j < 3; j++) {
  229. int _startY = ptStart.y + 15 + 50 * j;
  230. for (int i = 0; i < 4; i++) {
  231. int _startX = ptStart.x + 18 + i * 72;
  232. vecBoxPages.push_back(cv::Rect(_startX, _startY, ptPgW, ptPgH));
  233. if (vecBinStr[j * 4 + i])
  234. rectangle(img, vecBoxPages[vecBoxPages.size() - 1], cv::Scalar(0), -1);
  235. else
  236. rectangle(img, vecBoxPages[vecBoxPages.size() - 1], cv::Scalar(200, 200, 200), 2, 8, 0);
  237. }
  238. }
  239. return;
  240. }
  241. void generatePageJson(vector<cv::Rect>& vecPts, vector<cv::Rect>& vecBoxPages)
  242. {
  243. Json::Value imageSize;
  244. imageSize["width"] = 1654;
  245. imageSize["height"] = 2344;
  246. Json::Value location(Json::arrayValue);
  247. for (auto& iter : vecPts)
  248. {
  249. Json::Value item;
  250. item["x"] = iter.x;
  251. item["y"] = iter.y;
  252. item["width"] = iter.width;
  253. item["height"] = iter.height;
  254. location.append(item);
  255. }
  256. Json::Value pagenumber(Json::arrayValue);
  257. int nSubVecSize = 4;// 每个小vector的容量
  258. for (size_t i = 0, j = 1; i < vecBoxPages.size(); i += nSubVecSize)
  259. {
  260. vector<cv::Rect> vecSmall;
  261. auto last = std::min(vecBoxPages.size(), i + nSubVecSize);
  262. vecSmall.insert(vecSmall.begin(), vecBoxPages.begin() + i, vecBoxPages.begin() + last);
  263. Json::Value opt(Json::arrayValue);
  264. std::string choice[] = { "A", "B", "C", "D" };
  265. for (int h = 0; h < vecSmall.size(); h++)
  266. {
  267. Json::Value bin;
  268. bin["x"] = vecSmall[h].x;
  269. bin["y"] = vecSmall[h].y;
  270. bin["width"] = vecSmall[h].width;
  271. bin["height"] = vecSmall[h].height;
  272. bin["optName"] = choice[h];
  273. opt.append(bin);
  274. }
  275. Json::Value item;
  276. item["id"] = j;
  277. item["opt"] = opt;
  278. pagenumber.append(item);
  279. j++;
  280. }
  281. Json::Value itemRoot;
  282. itemRoot["imageSize"] = imageSize;
  283. itemRoot["location"] = location;
  284. itemRoot["pagenumber"] = pagenumber;
  285. Json::FastWriter writer;
  286. std::string strJson = writer.write(itemRoot);
  287. CFile zip;
  288. zip.Open(_T("D:\\page.json"), CFile::modeCreate | CFile::modeWrite);
  289. DWORD wide_string_len = MultiByteToWideChar(CP_ACP, 0, strJson.c_str(), -1, NULL, 0);
  290. WCHAR* wide_string = new WCHAR[wide_string_len];
  291. wide_string_len = MultiByteToWideChar(CP_ACP, 0, strJson.c_str(), -1, wide_string, wide_string_len);
  292. DWORD utf8_string_len = WideCharToMultiByte(CP_UTF8, 0, wide_string, -1, NULL, 0, NULL, NULL);
  293. CHAR* utf8_string = new CHAR[utf8_string_len];
  294. utf8_string_len = WideCharToMultiByte(CP_UTF8, 0, wide_string, -1, utf8_string, utf8_string_len, NULL, NULL);
  295. zip.Write((void*)utf8_string, utf8_string_len - 1);
  296. // LOG4CPLUS_INFO_FMT(pTestLogger, LOG4CPLUS_TEXT("%s"), CString(json_str.c_str()));
  297. delete wide_string;
  298. delete utf8_string;
  299. zip.Close();
  300. }
  301. std::string JsonToString(const Json::Value & root)
  302. {
  303. static Json::Value def = []{
  304. Json::Value def;
  305. Json::StreamWriterBuilder::setDefaults(&def);
  306. def["emitUTF8"] = true;
  307. return def;
  308. }();
  309. std::ostringstream stream;
  310. Json::StreamWriterBuilder stream_builder;
  311. stream_builder.settings_ = def;//Config emitUTF8
  312. std::unique_ptr<Json::StreamWriter> writer(stream_builder.newStreamWriter());
  313. writer->write(root, &stream);
  314. return stream.str();
  315. }
  316. int dataCollectionPaper(int cols, int index, int fontSize, int lineGrayPix, bool engShow, std::vector<string>& vecLines, CString dir, std::string& strPngPath) {
  317. /* 这里要做一些栏数 和 vecLines的对应值确认 */
  318. if (2 == cols && 14 * 2 == vecLines.size())
  319. ; // ok
  320. if (3 == cols && 14 * 3 == vecLines.size())
  321. ; // ok
  322. if (4 == cols && 14 * 4 == vecLines.size())
  323. ; // ok
  324. // 生成画布图像
  325. cv::Mat img(cv::Size(1654, 2344), CV_8UC3, cv::Scalar(255, 255, 255));
  326. int ptw = 80; int pth = 40;
  327. cv::Size fSize(0, 0);
  328. int leftPos = 100, rightPos = 1450;
  329. int topPos = 90;
  330. int fontW = rightPos - leftPos + ptw;
  331. vector<cv::Rect> vecPts = {
  332. cv::Rect(100,90,ptw,pth),
  333. cv::Rect(580,90,ptw,pth),
  334. cv::Rect(1450,90,ptw,pth),
  335. cv::Rect(100,2176,ptw,pth),
  336. cv::Rect(1450,2176,ptw,pth),
  337. };
  338. // 画定位点
  339. for (size_t i = 0; i < vecPts.size(); i++)
  340. {
  341. rectangle(img, vecPts[i], cv::Scalar(0, 0, 0), -1);
  342. }
  343. // 画示例框
  344. topPos += pth; topPos += 30;
  345. rectangle(img, cv::Rect(leftPos, topPos, fontW, 200), cv::Scalar(0, 0, 0), 2, 8, 0);
  346. // 画页码框
  347. cv::Rect boxPageNumber(leftPos + fontW - 300, topPos, 300, 200);
  348. rectangle(img, boxPageNumber, cv::Scalar(0, 0, 0), 2, 8, 0);
  349. // 生成二进制码流
  350. /* 二进制码流的坐标在下面函数里面实现,需要用书写获取 */
  351. vector<cv::Rect> vecBoxPages;
  352. createBinString(img, index, ptw, pth, cv::Point(boxPageNumber.x, boxPageNumber.y), vecBoxPages);
  353. string strPageNumInfo = "关联ID: " + to_string(index);
  354. putTextZH(img, fSize, strPageNumInfo.c_str(), cv::Point(boxPageNumber.x + 100, boxPageNumber.y + 50 * 2 + 20 + 15 + 15 + 15), Scalar(0), 20, "宋体");
  355. // 生成page.json
  356. //generatePageJson(vecPts, vecBoxPages);
  357. // 画警示信息
  358. string strMesInfo = "1、请在每题下方的横线上书写本题的内容!\
  359. \n\n2、题号不需要书写,标点符号需要原样书写。☆\
  360. \n\n3、如果本题书写有误,进行了涂抹修改等操作,请将题号前矩形框用任意笔进行填涂!☆☆\n";
  361. putTextZH(img, fSize, strMesInfo.c_str(), cv::Point(leftPos + 20, topPos + 20), Scalar(0), 25, "宋体");
  362. int lineTop1 = topPos + 20 + fSize.height + 20;
  363. cv::line(img, cv::Point(leftPos, lineTop1), cv::Point(rightPos + ptw - 300, topPos + 20 + fSize.height + 20), Scalar(0), 2, 8, 0);
  364. // 正确示例
  365. string strEgInfo = "正\n确\n示\n例";
  366. putTextZH(img, fSize, strEgInfo.c_str(), cv::Point(leftPos + 20, topPos + 20 + fSize.height + 20 + 3), Scalar(0), 20, "宋体");
  367. cv::line(img, cv::Point(leftPos + 20 + fSize.width + 10, lineTop1), cv::Point(leftPos + 20 + fSize.width + 10, topPos + 200), Scalar(0, 0, 0), 2, 8, 0);
  368. // 贴图区域
  369. /* 暂不实现 */
  370. topPos += 200;
  371. // 文字区域
  372. static int maxLineNum = 14; // 最大行数14
  373. static int ttBoxWidth = 30; // 填涂框的边长
  374. static int tiSl = 10; // 题号和题干间的距离
  375. static int lineDis = 20; // 两行之间的距离
  376. int colWidth = fontW / cols; // 单栏的宽度
  377. fSize.width = 0; fSize.height = 0;
  378. Json::Value root(Json::arrayValue);
  379. for (int col = 0; col < cols; col++)
  380. { // 逐栏画题
  381. int colTopPos = topPos;
  382. int colLeftPos = leftPos + col * colWidth;
  383. for (size_t i = 0; i < maxLineNum; i++)
  384. {
  385. size_t vecIndex = i + col * maxLineNum;
  386. if (vecIndex >= vecLines.size())
  387. {
  388. break;
  389. }
  390. colTopPos += lineDis;
  391. int lineLen = ttBoxWidth + tiSl;
  392. // 画填涂框 30*30 大小
  393. cv::Rect rcbox(colLeftPos, colTopPos, ttBoxWidth, ttBoxWidth);
  394. rectangle(img, rcbox, cv::Scalar(0), 1, 8, 0);
  395. int iQNum = i + 1 + col * maxLineNum;
  396. string strStinfo = to_string(iQNum); strStinfo += ".";
  397. cv::Point ptNum(colLeftPos + ttBoxWidth + tiSl, colTopPos);
  398. putTextZH(img, fSize, strStinfo.c_str(), ptNum, Scalar(0, 0, 0), fontSize, "宋体"); // 跟填涂框保持10px距离
  399. lineLen += fSize.width;
  400. cv::Rect rcNum(ptNum.x, ptNum.y, fSize.width, fSize.height);
  401. strStinfo.clear();
  402. string strTgInfo = vecLines[vecIndex];
  403. if (!engShow)
  404. ; /* 移除词性 */
  405. //char szTemp[2048];
  406. //memset(szTemp, 0, sizeof(char)*(2048));
  407. //UTF82ANSI(strTgInfo.c_str(), strTgInfo.length(), szTemp, 2048);
  408. //strTgInfo = szTemp;
  409. cv::Point ptQues(colLeftPos + ttBoxWidth + tiSl + fSize.width, colTopPos);
  410. putTextZH(img, fSize, strTgInfo.c_str(), ptQues, Scalar(0, 0, 0), fontSize, "宋体"); // 跟填涂框保持10px距离
  411. lineLen += fSize.width;
  412. cv::Rect rcQues(ptQues.x, ptQues.y, fSize.width, fSize.height);
  413. cv::Rect rcAns(colLeftPos + 30, colTopPos + fSize.height, colWidth - ttBoxWidth, 1);
  414. colTopPos = colTopPos + fSize.height * 3.5; //两行之间两倍的距离用于书写
  415. line(img, cv::Point(colLeftPos + 30, colTopPos), cv::Point(colLeftPos + colWidth - 1, colTopPos), Scalar(lineGrayPix, lineGrayPix, lineGrayPix), 1, 8, 0);
  416. rcAns.height = colTopPos - rcAns.y + lineDis;
  417. //生成识别信息
  418. Json::Value ttbox;
  419. ttbox["x"] = rcbox.x;
  420. ttbox["y"] = rcbox.y;
  421. ttbox["width"] = rcbox.width;
  422. ttbox["height"] = rcbox.height;
  423. Json::Value queNum;
  424. queNum["x"] = rcNum.x;
  425. queNum["y"] = rcNum.y;
  426. queNum["width"] = rcNum.width;
  427. queNum["height"] = rcNum.height;
  428. Json::Value queInfo;
  429. queInfo["x"] = rcQues.x;
  430. queInfo["y"] = rcQues.y;
  431. queInfo["width"] = rcQues.width;
  432. queInfo["height"] = rcQues.height;
  433. queInfo["info"] = strTgInfo.c_str();
  434. Json::Value ansInfo;
  435. ansInfo["x"] = rcAns.x;
  436. ansInfo["y"] = rcAns.y;
  437. ansInfo["width"] = rcAns.width;
  438. ansInfo["height"] = rcAns.height;
  439. Json::Value item;
  440. item["id"] = iQNum;
  441. item["ttbox"] = ttbox;
  442. item["queNum"] = queNum;
  443. item["queInfo"] = queInfo;
  444. item["ansInfo"] = queInfo;
  445. root.append(item);
  446. // test
  447. /*rectangle(img, rcbox, cv::Scalar(0, 0, 200), 1, 8, 0);
  448. rectangle(img, rcNum, cv::Scalar(0, 200, 0), 1, 8, 0);
  449. rectangle(img, rcQues, cv::Scalar(100, 0, 0), 1, 8, 0);
  450. rectangle(img, rcAns, cv::Scalar(200, 0, 0), 1, 8, 0);*/
  451. }
  452. }
  453. std::string strJson = JsonToString(root);
  454. CString strTemplatePath;
  455. strTemplatePath.Format(L"%s/json/%d.json", dir, index);
  456. CFile zip;
  457. zip.Open(strTemplatePath, CFile::modeCreate | CFile::modeWrite);
  458. zip.Write((void*)strJson.c_str(), strJson.length());
  459. zip.Close();
  460. wchar_t tempPath[MAX_PATH];
  461. DWORD dwSize = MAX_PATH;
  462. GetTempPath(dwSize, tempPath);//获取临时文件夹路径
  463. static int tmp_index = 1;
  464. wchar_t szPath[MAX_PATH];
  465. _stprintf(szPath, L"%stmp_%d.png", tempPath, tmp_index);
  466. tmp_index++;
  467. if (tmp_index > 10)
  468. {
  469. tmp_index = 1;
  470. }
  471. strPngPath = TstringToGB2312(szPath);
  472. cv::imwrite(strPngPath, img);
  473. /*cv::namedWindow("fuck", 1);
  474. cv::imshow("fuck", img);
  475. cv::waitKey(0);*/
  476. return 0;
  477. }