|
@@ -28,6 +28,15 @@ void GetStringSize(HDC hDC, const char* str, int* w, int* h)
|
|
if (h != 0) *h = size.cy;
|
|
if (h != 0) *h = size.cy;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+cv::Size GetImgSize(const char* strpath, double scale)
|
|
|
|
+{
|
|
|
|
+ cv::Mat img = cv::imread(strpath);
|
|
|
|
+ cv::Size size;
|
|
|
|
+ size.width = img.cols*scale;
|
|
|
|
+ size.height = img.rows*scale;
|
|
|
|
+ return size;
|
|
|
|
+}
|
|
|
|
+
|
|
cv::Size GetTextSize(const char* str, int fontSize, const char* fn, bool italic, bool underline)
|
|
cv::Size GetTextSize(const char* str, int fontSize, const char* fn, bool italic, bool underline)
|
|
{
|
|
{
|
|
HDC hDC = CreateCompatibleDC(0);
|
|
HDC hDC = CreateCompatibleDC(0);
|
|
@@ -372,7 +381,283 @@ std::string JsonToString(const Json::Value & root)
|
|
return stream.str();
|
|
return stream.str();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+int dataCollectionPaperFormula(int cols, int index, int fontSize, int lineGrayPix, bool engShow,
|
|
|
|
+ std::vector<tuple<string, string>>& vecLines, CString dir, std::string& strPngPath, std::string tips, size_t &icount)
|
|
|
|
+{
|
|
|
|
+ /* 这里要做一些栏数 和 vecLines的对应值确认 */
|
|
|
|
+ if (2 == cols && 14 * 2 == vecLines.size())
|
|
|
|
+ ; // ok
|
|
|
|
+ if (3 == cols && 14 * 3 == vecLines.size())
|
|
|
|
+ ; // ok
|
|
|
|
+ if (4 == cols && 14 * 4 == vecLines.size())
|
|
|
|
+ ; // ok
|
|
|
|
+
|
|
|
|
+ HMODULE module = GetModuleHandle(0);
|
|
|
|
+ TCHAR pFileName[MAX_PATH + 2] = { 0 };
|
|
|
|
+ GetModuleFileName(module, pFileName, MAX_PATH);
|
|
|
|
+ CString csFullPath(pFileName);
|
|
|
|
+ int nPos = csFullPath.ReverseFind(_T('\\'));
|
|
|
|
+ CString filepath = csFullPath.Left(nPos);
|
|
|
|
+ CString FilePath1 = filepath + L"\\config.ini";
|
|
|
|
+ WCHAR wScale[10],wh[10],wlineDis[10],wDraw[10];
|
|
|
|
+ GetPrivateProfileString(L"USER", L"Scale", L"1.0", wScale, 10, FilePath1);
|
|
|
|
+ GetPrivateProfileString(L"USER", L"WirteHScale", L"1.5", wh, 10, FilePath1);
|
|
|
|
+ GetPrivateProfileString(L"USER", L"LineDis", L"30", wlineDis, 10, FilePath1);
|
|
|
|
+ GetPrivateProfileString(L"USER", L"Draw", L"0", wDraw, 10, FilePath1);
|
|
|
|
+ double scale = _wtof(wScale);
|
|
|
|
+ double wirteH = _wtof(wh);
|
|
|
|
+ int mylineDis= _wtof(wlineDis);
|
|
|
|
+ int drawflag = _wtoi(wDraw);
|
|
|
|
+
|
|
|
|
+ // 生成画布图像
|
|
|
|
+ cv::Mat img(cv::Size(1654, 2344), CV_8UC3, cv::Scalar(255, 255, 255));
|
|
|
|
+ int ptw = 80; int pth = 40;
|
|
|
|
+ cv::Size fSize(0, 0);
|
|
|
|
+ int leftPos = 100, rightPos = 1450;
|
|
|
|
+ int topPos = 90;
|
|
|
|
+ int fontW = rightPos - leftPos + ptw;
|
|
|
|
+ vector<cv::Rect> vecPts = {
|
|
|
|
+ cv::Rect(100,90,ptw,pth),
|
|
|
|
+ cv::Rect(580,90,ptw,pth),
|
|
|
|
+ cv::Rect(1450,90,ptw,pth),
|
|
|
|
+ cv::Rect(100,2176,ptw,pth),
|
|
|
|
+ cv::Rect(1450,2176,ptw,pth),
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // 画定位点
|
|
|
|
+ for (size_t i = 0; i < vecPts.size(); i++)
|
|
|
|
+ {
|
|
|
|
+ rectangle(img, vecPts[i], cv::Scalar(0, 0, 0), -1);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 画示例框
|
|
|
|
+ topPos += pth; topPos += 30;
|
|
|
|
+ rectangle(img, cv::Rect(leftPos, topPos, fontW, 200), cv::Scalar(0, 0, 0), 2, 8, 0);
|
|
|
|
+
|
|
|
|
+ // 画页码框
|
|
|
|
+ cv::Rect boxPageNumber(leftPos + fontW - 300, topPos, 300, 200);
|
|
|
|
+ rectangle(img, boxPageNumber, cv::Scalar(0, 0, 0), 2, 8, 0);
|
|
|
|
|
|
|
|
+ // 生成二进制码流
|
|
|
|
+ /* 二进制码流的坐标在下面函数里面实现,需要用书写获取 */
|
|
|
|
+ vector<cv::Rect> vecBoxPages;
|
|
|
|
+ createBinString(img, index, ptw, pth, cv::Point(boxPageNumber.x, boxPageNumber.y), vecBoxPages);
|
|
|
|
+ string strPageNumInfo = "关联ID: " + to_string(index);
|
|
|
|
+ putTextZH(img, fSize, strPageNumInfo.c_str(), cv::Point(boxPageNumber.x + 100, boxPageNumber.y + 50 * 2 + 20 + 15 + 15 + 15), Scalar(0), 20, "宋体");
|
|
|
|
+
|
|
|
|
+ // 生成page.json
|
|
|
|
+ //generatePageJson(vecPts, vecBoxPages);
|
|
|
|
+
|
|
|
|
+ // 画警示信息
|
|
|
|
+ string strMesInfo = "1、请在对应的区域内临摹左侧电路图,每个方框内一个!\
|
|
|
|
+ \n\n2、可以使用铅笔和黑色笔绘图。☆\
|
|
|
|
+ \n\n3、如果本框内有绘画错误,进行了涂抹修改等操作,请将左上方的填涂框用任意笔进行填涂!☆☆\n";
|
|
|
|
+ if (tips.length() > 0)
|
|
|
|
+ {
|
|
|
|
+ strMesInfo = tips;
|
|
|
|
+ }
|
|
|
|
+ putTextZH(img, fSize, strMesInfo.c_str(), cv::Point(leftPos + 20, topPos + 20), Scalar(0), 25, "宋体");
|
|
|
|
+ int lineTop1 = topPos + 20 + fSize.height + 20;
|
|
|
|
+ cv::line(img, cv::Point(leftPos, lineTop1), cv::Point(rightPos + ptw - 300, topPos + 20 + fSize.height + 20), Scalar(0), 2, 8, 0);
|
|
|
|
+
|
|
|
|
+ // 正确示例
|
|
|
|
+ string strEgInfo = "注\n意\n事\n项";
|
|
|
|
+ putTextZH(img, fSize, strEgInfo.c_str(), cv::Point(leftPos + 20, topPos + 20 + fSize.height + 20 + 3), Scalar(0), 20, "宋体");
|
|
|
|
+ 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);
|
|
|
|
+
|
|
|
|
+ // 填涂示例
|
|
|
|
+ string strtt = "1、抄写时保持公式的结构与题目内结构相对一致!切勿发生严重变形!\
|
|
|
|
+ \n\n2、题号 \"n.\"不需要抄写";
|
|
|
|
+ cv::Point ptEgInfo(leftPos + 70, topPos + 20 + fSize.height + 20 + 15);
|
|
|
|
+ putTextZH(img, fSize, strtt.c_str(), ptEgInfo, Scalar(0), 20, "宋体");
|
|
|
|
+
|
|
|
|
+ //cv::Rect rcttbox(ptEgInfo.x + 100, ptEgInfo.y - 5, 30, 30);
|
|
|
|
+ //rectangle(img, rcttbox, cv::Scalar(0), -1);
|
|
|
|
+ //rcttbox.x += 1;
|
|
|
|
+ //rcttbox.y += 1;
|
|
|
|
+ //rcttbox.width -= 2;
|
|
|
|
+ //rcttbox.height -= 2;
|
|
|
|
+ //rectangle(img, rcttbox, cv::Scalar(100, 100, 100), -1);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // 贴图区域
|
|
|
|
+ /* 暂不实现 */
|
|
|
|
+
|
|
|
|
+ topPos += 200;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ ///////////////////////////////////////// 主干区域: y 起始坐标:360/////////////////////////////////////////////
|
|
|
|
+ Json::Value root(Json::arrayValue);
|
|
|
|
+
|
|
|
|
+ // +指定像素
|
|
|
|
+ auto yhPadding = [&](cv::Rect & rcBox, int pd) {
|
|
|
|
+ rcBox.x += pd;
|
|
|
|
+ rcBox.y += pd;
|
|
|
|
+ rcBox.width -= (pd * 2);
|
|
|
|
+ rcBox.height -= (pd * 2);
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ // json valule
|
|
|
|
+ auto addValueToJson = [&](Json::Value & root, cv::Rect rcbox, cv::Rect rcNum, cv::Rect rcQues, cv::Rect rcAns,
|
|
|
|
+ int iQNum, std::string strTgInfo, std::string strSolution) {
|
|
|
|
+ //生成识别信息
|
|
|
|
+ Json::Value ttbox;
|
|
|
|
+ ttbox["x"] = rcbox.x;
|
|
|
|
+ ttbox["y"] = rcbox.y;
|
|
|
|
+ ttbox["width"] = rcbox.width;
|
|
|
|
+ ttbox["height"] = rcbox.height;
|
|
|
|
+
|
|
|
|
+ Json::Value queNum;
|
|
|
|
+ queNum["x"] = rcNum.x;
|
|
|
|
+ queNum["y"] = rcNum.y;
|
|
|
|
+ queNum["width"] = rcNum.width;
|
|
|
|
+ queNum["height"] = rcNum.height;
|
|
|
|
+
|
|
|
|
+ Json::Value queInfo;
|
|
|
|
+ queInfo["x"] = rcQues.x;
|
|
|
|
+ queInfo["y"] = rcQues.y;
|
|
|
|
+ queInfo["width"] = rcQues.width;
|
|
|
|
+ queInfo["height"] = rcQues.height;
|
|
|
|
+ queInfo["info"] = strTgInfo.c_str();
|
|
|
|
+ queInfo["solution"] = strSolution.c_str();
|
|
|
|
+
|
|
|
|
+ Json::Value ansInfo;
|
|
|
|
+ ansInfo["x"] = rcAns.x;
|
|
|
|
+ ansInfo["y"] = rcAns.y;
|
|
|
|
+ ansInfo["width"] = rcAns.width;
|
|
|
|
+ ansInfo["height"] = rcAns.height;
|
|
|
|
+
|
|
|
|
+ Json::Value item;
|
|
|
|
+ item["id"] = iQNum;
|
|
|
|
+ item["ttbox"] = ttbox;
|
|
|
|
+ item["queNum"] = queNum;
|
|
|
|
+ item["queInfo"] = queInfo;
|
|
|
|
+ item["ansInfo"] = ansInfo;
|
|
|
|
+
|
|
|
|
+ root.append(item);
|
|
|
|
+ };
|
|
|
|
+ static int maxHight = 2140;
|
|
|
|
+ static int ttBoxWidth = 30; // 填涂框的边长
|
|
|
|
+ static int tiSl = 10; // 题号和题干间的距离
|
|
|
|
+ int lineDis = 30; // 两行之间的距离
|
|
|
|
+ int colWidth = fontW / cols; // 单栏的宽度
|
|
|
|
+ fSize.width = 0; fSize.height = 0;
|
|
|
|
+ int iQNum = 1;
|
|
|
|
+
|
|
|
|
+ //Json::Value root(Json::arrayValue);
|
|
|
|
+
|
|
|
|
+ for (int col = 0; col < cols; col++)
|
|
|
|
+ {
|
|
|
|
+ int colTopPos = topPos;
|
|
|
|
+ int colLeftPos = leftPos + col * colWidth;
|
|
|
|
+ colTopPos += 20;
|
|
|
|
+ while (vecLines.size() > icount )
|
|
|
|
+ {
|
|
|
|
+ string strTgInfo = std::get<0>(vecLines[icount]);
|
|
|
|
+ string strSolution = std::get<1>(vecLines[icount]);
|
|
|
|
+ cv::Mat _img = cv::imread(strTgInfo, cv::IMREAD_ANYCOLOR);
|
|
|
|
+ //贴图高度计算
|
|
|
|
+ int h,ih,w;
|
|
|
|
+ h = _img.rows*scale;// < 30 ? 30 : _img.rows*scale;
|
|
|
|
+ lineDis = mylineDis;
|
|
|
|
+ ih = h + h * wirteH + lineDis;
|
|
|
|
+ if (maxHight < ih + colTopPos)
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ int lineLen = ttBoxWidth + tiSl;
|
|
|
|
+ // 画填涂框 30*30 大小
|
|
|
|
+ cv::Rect rcbox(colLeftPos, colTopPos, ttBoxWidth, ttBoxWidth);
|
|
|
|
+ rectangle(img, rcbox, cv::Scalar(0), 1, 8, 0);
|
|
|
|
+ string strStinfo = to_string(iQNum); strStinfo += ".";
|
|
|
|
+ cv::Point ptNum(colLeftPos + ttBoxWidth + tiSl, colTopPos);
|
|
|
|
+ putTextZH(img, fSize, strStinfo.c_str(), ptNum, Scalar(0, 0, 0), fontSize, "宋体"); // 跟填涂框保持10px距离
|
|
|
|
+ lineLen += fSize.width;
|
|
|
|
+ cv::Rect rcNum(ptNum.x, ptNum.y, fSize.width, fSize.height);
|
|
|
|
+
|
|
|
|
+ cv::Point ptQues(colLeftPos + ttBoxWidth + tiSl + fSize.width, colTopPos);
|
|
|
|
+ cv::Mat sizeimg(cv::Size(_img.cols*scale, _img.rows*scale), CV_32S);
|
|
|
|
+ cv::resize(_img, sizeimg, cv::Size(_img.cols*scale, _img.rows*scale));
|
|
|
|
+ cv::Mat bgROIMat = img(Rect(ptQues.x, ptQues.y, _img.cols*scale, _img.rows*scale));
|
|
|
|
+ sizeimg.copyTo(bgROIMat);
|
|
|
|
+ if (drawflag != 0)
|
|
|
|
+ rectangle(img, Rect(ptQues.x, ptQues.y, _img.cols*scale, _img.rows*scale), cv::Scalar(0, 0, 255), 2, 8, 0);
|
|
|
|
+
|
|
|
|
+ cv::Rect rcQues(ptQues.x, ptQues.y, fSize.width, fSize.height);
|
|
|
|
+ cv::Rect rcAns(colLeftPos + 30, colTopPos + h, colWidth - ttBoxWidth, 1);
|
|
|
|
+
|
|
|
|
+ colTopPos = colTopPos + h + wirteH *h; //两行之间两倍的距离用于书写
|
|
|
|
+ //lineGrayPix = rng.operator ()(220);
|
|
|
|
+ line(img, cv::Point(colLeftPos + 30, colTopPos), cv::Point(colLeftPos + colWidth - 5, colTopPos), Scalar(lineGrayPix, lineGrayPix, lineGrayPix), 1, 8, 0);
|
|
|
|
+ rcAns.height = colTopPos - rcAns.y + lineDis;
|
|
|
|
+ colTopPos += lineDis;
|
|
|
|
+ if(drawflag != 0)
|
|
|
|
+ rectangle(img, rcAns, cv::Scalar(0, 255, 0), 2, 8, 0);
|
|
|
|
+
|
|
|
|
+ //生成识别信息
|
|
|
|
+ Json::Value ttbox;
|
|
|
|
+ ttbox["x"] = rcbox.x;
|
|
|
|
+ ttbox["y"] = rcbox.y;
|
|
|
|
+ ttbox["width"] = rcbox.width;
|
|
|
|
+ ttbox["height"] = rcbox.height;
|
|
|
|
+
|
|
|
|
+ Json::Value queNum;
|
|
|
|
+ queNum["x"] = rcNum.x;
|
|
|
|
+ queNum["y"] = rcNum.y;
|
|
|
|
+ queNum["width"] = rcNum.width;
|
|
|
|
+ queNum["height"] = rcNum.height;
|
|
|
|
+
|
|
|
|
+ Json::Value queInfo;
|
|
|
|
+ queInfo["x"] = rcQues.x;
|
|
|
|
+ queInfo["y"] = rcQues.y;
|
|
|
|
+ queInfo["width"] = rcQues.width;
|
|
|
|
+ queInfo["height"] = rcQues.height;
|
|
|
|
+ queInfo["info"] = strSolution.c_str();
|
|
|
|
+
|
|
|
|
+ Json::Value ansInfo;
|
|
|
|
+ ansInfo["x"] = rcAns.x;
|
|
|
|
+ ansInfo["y"] = rcAns.y;
|
|
|
|
+ ansInfo["width"] = rcAns.width;
|
|
|
|
+ ansInfo["height"] = rcAns.height;
|
|
|
|
+
|
|
|
|
+ Json::Value item;
|
|
|
|
+ item["id"] = iQNum;
|
|
|
|
+ item["ttbox"] = ttbox;
|
|
|
|
+ item["queNum"] = queNum;
|
|
|
|
+ item["queInfo"] = queInfo;
|
|
|
|
+ item["ansInfo"] = ansInfo;
|
|
|
|
+ iQNum++;
|
|
|
|
+ icount++;
|
|
|
|
+ root.append(item);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ //cv::Mat img = cv::imread(strTgInfo, cv::IMREAD_ANYCOLOR);
|
|
|
|
+ std::string strJson = JsonToString(root);
|
|
|
|
+
|
|
|
|
+ CString strTemplatePath;
|
|
|
|
+ strTemplatePath.Format(L"%s/json/%d.json", dir, index);
|
|
|
|
+ CFile zip;
|
|
|
|
+ zip.Open(strTemplatePath, CFile::modeCreate | CFile::modeWrite);
|
|
|
|
+ zip.Write((void*)strJson.c_str(), strJson.length());
|
|
|
|
+ zip.Close();
|
|
|
|
+
|
|
|
|
+ wchar_t tempPath[MAX_PATH];
|
|
|
|
+ DWORD dwSize = MAX_PATH;
|
|
|
|
+ GetTempPath(dwSize, tempPath);//获取临时文件夹路径
|
|
|
|
+ static int tmp_index = 1;
|
|
|
|
+ wchar_t szPath[MAX_PATH];
|
|
|
|
+ _stprintf(szPath, L"%stmp_%d.png", tempPath, tmp_index);
|
|
|
|
+ tmp_index++;
|
|
|
|
+ if (tmp_index > 10)
|
|
|
|
+ {
|
|
|
|
+ tmp_index = 1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ strPngPath = TstringToGB2312(szPath);
|
|
|
|
+ cv::imwrite(strPngPath, img);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
|
|
int dataCollectionPaperPhysics(int cols, int index, int fontSize, int lineGrayPix, bool engShow,
|
|
int dataCollectionPaperPhysics(int cols, int index, int fontSize, int lineGrayPix, bool engShow,
|
|
std::vector<tuple<string, string>>& vecLines, CString dir, std::string& strPngPath, std::string tips) {
|
|
std::vector<tuple<string, string>>& vecLines, CString dir, std::string& strPngPath, std::string tips) {
|
|
@@ -442,7 +727,7 @@ int dataCollectionPaperPhysics(int cols, int index, int fontSize, int lineGrayPi
|
|
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);
|
|
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);
|
|
|
|
|
|
// 填涂示例
|
|
// 填涂示例
|
|
- string strtt = "尽量保持手绘内容与示例图相对位置一致!即保持整体相对居中!";
|
|
|
|
|
|
+ string strtt = "要保持手写结构保持原结构,局部涂抹也算涂抹,需要填涂!!!!题号. 不需要抄写 !!!";
|
|
cv::Point ptEgInfo(leftPos + 70, topPos + 20 + fSize.height + 20 + 30);
|
|
cv::Point ptEgInfo(leftPos + 70, topPos + 20 + fSize.height + 20 + 30);
|
|
putTextZH(img, fSize, strtt.c_str(), ptEgInfo, Scalar(0), 20, "宋体");
|
|
putTextZH(img, fSize, strtt.c_str(), ptEgInfo, Scalar(0), 20, "宋体");
|
|
|
|
|