#include "StdAfx.h" #include "BatchService.h" #include "scan_common.h" #include "..\EvaluationUtil\HttpClient.h" #include "..\Schema\schema_struct.h" #include "SchemaLoader.h" #include "basic_struct_result.h" #include "..\Identifier\schema_struct.h" #include "ServerConfig.h" //#include "Log4cplusInitalizer.h" #include "TemplateManager.h" #include "resource.h" #include "IdentifyService.h" #include "ResultUploader.h" #include #include #include "OnlineCardIdentifyService.h" #include #include "../Identifier/OnLineCardSchemaStruct.h" #include "..\ZLibWrapMemLib\UnZipFile.h" #include "..\ZLibWrapMemLib\MemZipFile.h" #include "..\ZLibWrapLib\ZLibWrapLib.h" #include "OnlineCardStudentMatcher.h" #include "ResultUploader.h" #include #include "../Identifier/PageIdentify.h" int m_nSubjectID = 0; CString GetExePath(); CString AnsiToUnicode(const std::string& str); std::string UnicodeToAnsi(const CString& str); using namespace schema; using namespace OnLineCard; OnLineCard::PaperTemplate* m_onlineCardTemplate = new OnLineCard::PaperTemplate; bool ParseTemplateFromJsonAll(const std::string&fileName)//全学科在线答题卡 { extern bool g_isAllSubject;//是否是全学科 g_isAllSubject = 1; //1 单选 2 小题单选 3 多选 4 小题多选 5 单空 6 多空 7 小题多空 8 解答 9 小题解答 10 英语作文 11 语文作文 12 判断题 //0选择 1解答 2选作 3填空 4编组 5不定项 8不定项 map type_map;//新旧题型对应 type_map["1"] = 0; type_map["2"] = 0; type_map["3"] = 5; type_map["4"] = 5; type_map["5"] = 3; type_map["6"] = 3; type_map["7"] = 3; type_map["8"] = 1; type_map["9"] = 1; type_map["12"] = 0; /*type_map["10"] = 1; type_map["11"] = 1; */ CUnZipFile uzip(CString(fileName.c_str())); std::map> map1; while (uzip.HasMoreEntry()){ CString fileNam; uzip.GetNextEntry(fileNam); char buffer[1024 * 8]; int len; std::vector& data = map1[fileNam]; data.reserve(1024 * 128); while ((len = uzip.Read(buffer, 1024 * 8)) > 0){ if (data.capacity() < data.size() + len){ int c = data.capacity() + 1024 * 128; data.reserve(c); } int oldSize = data.size(); data.resize(oldSize + len); char * dst = (char *)data.data() + oldSize; memcpy(dst, buffer, len); } } uzip.Close(); auto schemabytes = map1.find(_T("json.txt")); if (schemabytes == map1.end()){ return SCH_LOAD_ERR_MISSINGFORMAT; } std::vector& data = schemabytes->second; auto strJson = std::string((char *)data.data(), data.size()); if (!m_onlineCardTemplate) return false; m_onlineCardTemplate->pages.clear(); auto pfGetPos = [](const rapidjson::Value&value)->std::tuple{ bool bRet = false; double x = 0.0, y = 0.0, w = 0.0, h = 0.0; auto itX = value.FindMember("x"); if (itX != value.MemberEnd() && (itX->value.IsInt() || itX->value.IsDouble())){ x = itX->value.GetDouble(); } auto itY = value.FindMember("y"); if (itY != value.MemberEnd() && (itY->value.IsInt() || itY->value.IsDouble())){ y = itY->value.GetDouble(); } auto itW = value.FindMember("width"); if (itW != value.MemberEnd() && (itW->value.IsInt() || itW->value.IsDouble())){ w = itW->value.GetDouble(); } auto itH = value.FindMember("height"); if (itH != value.MemberEnd() && (itH->value.IsInt() || itH->value.IsDouble())){ h = itH->value.GetDouble(); bRet = true; } return std::tie(bRet, Pos{ x, y, w, h }); }; rapidjson::Document doc; doc.Parse(strJson.c_str()); if (doc.HasParseError()) return false; m_onlineCardTemplate->subject_id = m_nSubjectID; m_onlineCardTemplate->_version = "3.1.0"; // 检测版本号 auto it_version = doc.FindMember("online_card_version"); if (it_version != doc.MemberEnd() && it_version->value.IsString()){ m_onlineCardTemplate->_version = it_version->value.GetString(); } LOGFMTI("在线答题卡版本号:%s", m_onlineCardTemplate->_version.c_str()); { // 总页数 auto itTotalPage = doc.FindMember("totalPage"); if (itTotalPage != doc.MemberEnd() && itTotalPage->value.IsInt()){ m_onlineCardTemplate->totalPage = itTotalPage->value.GetInt(); } // 是否使用二维码 auto itUseQrCode = doc.FindMember("useQrCode"); if (itUseQrCode != doc.MemberEnd() && itUseQrCode->value.IsBool()){ m_onlineCardTemplate->useQrCode = itUseQrCode->value.GetBool(); } if (itUseQrCode != doc.MemberEnd() && itUseQrCode->value.IsInt()){ m_onlineCardTemplate->useQrCode = (itUseQrCode->value.GetInt() != 0); } // 学校状态 auto itSchoolStatus = doc.FindMember("school_card_status"); if (itSchoolStatus != doc.MemberEnd() && itSchoolStatus->value.IsInt()){ m_onlineCardTemplate->schoolCardStatus = itSchoolStatus->value.GetInt(); } int n_duo_xuanti_index = 0; std::string temp_all_id = ""; // 页 auto itPages = doc.FindMember("pages"); if (itPages != doc.MemberEnd() && itPages->value.IsArray()/* && itPages->value.Size() == m_onlineCardTemplate->totalPage*/){ for (auto itPage = itPages->value.Begin(); itPage != itPages->value.End(); ++itPage){ if (!itPage->IsObject()) return false; PageTemplate page; // 页号 auto itPageNo = itPage->FindMember("pageNo"); if (itPageNo != itPage->MemberEnd() && itPageNo->value.IsInt()){ page.pageNo = itPageNo->value.GetInt(); } else { return false; } // 定位点 auto itLocations = itPage->FindMember("location"); if (itLocations != itPage->MemberEnd() && itLocations->value.IsArray()){ for (auto it = itLocations->value.Begin(); it != itLocations->value.End(); ++it){ Location lc; auto itType = it->FindMember("type"); if (itType != it->MemberEnd() && itType->value.IsInt()){ lc.type = itType->value.GetInt(); } auto tm = pfGetPos(*it); if (std::get<0>(tm)){ lc.pos = std::get<1>(tm); } page.location.push_back(lc); } } if (page.pageNo == 1){ if (!m_onlineCardTemplate->useQrCode){ // 条形码 auto itBar = itPage->FindMember("studentcode_bar"); if (itBar != itPage->MemberEnd() && itBar->value.IsObject()){ auto itObj = itBar->value.FindMember("object"); if (itObj != itBar->value.MemberEnd() && itObj->value.IsObject()){ auto t = pfGetPos(itObj->value); page.studentcode_bar = std::get<1>(t); } } // 填涂考号 auto itFill = itPage->FindMember("studentcode_fill"); if (itFill != itPage->MemberEnd() && itFill->value.IsObject()){ auto itObj = itFill->value.FindMember("object"); if (itObj != itFill->value.MemberEnd() && itObj->value.IsArray()){ for (auto itRow = itObj->value.Begin(); itRow != itObj->value.End(); ++itRow){ auto itGroup = itRow->FindMember("group"); if (itGroup != itRow->MemberEnd() && itGroup->value.IsArray()){ std::vector _vctOpt; for (auto itCol = itGroup->value.Begin(); itCol != itGroup->value.End(); ++itCol){ Opt opt; auto itOptName = itCol->FindMember("optName"); if (itOptName != itCol->MemberEnd() && itOptName->value.IsInt()) opt.optName = std::to_string(itOptName->value.GetInt()); auto t = pfGetPos(*itCol); if (std::get<0>(t)) opt.pos = std::get<1>(t); _vctOpt.push_back(opt); } page.studentcode_fill.push_back(_vctOpt); } } } } } // 缺考标记 auto itAbsent = itPage->FindMember("absent"); if (itAbsent != itPage->MemberEnd() && itAbsent->value.IsObject()){ auto t = pfGetPos(itAbsent->value); if (std::get<0>(t)){ page.absent = std::get<1>(t); } } // 二维码 auto itQrCode = itPage->FindMember("QrCode"); if (itQrCode != itPage->MemberEnd() && itQrCode->value.IsObject()){ auto t = pfGetPos(itQrCode->value); if (std::get<0>(t)){ page.QrCode = std::get<1>(t); } } } // end if page.pageNo == 0 // 长宽 auto itImge = itPage->FindMember("imge"); if (itImge != itPage->MemberEnd()){ auto t = std::get<1>(pfGetPos(itImge->value)); page.w = t.w; page.h = t.h; } else{ return false; } // 题目 auto itQuestion = itPage->FindMember("questions"); if (itQuestion != itPage->MemberEnd() && itQuestion->value.IsArray()) { for (auto it = itQuestion->value.Begin(); it != itQuestion->value.End(); ++it) { question q; // 题目类型 auto itType = it->FindMember("type"); string qType = "1"; if (itType != it->MemberEnd() && itType->value.IsString()) { qType = itType->value.GetString(); if (type_map.find(qType) != type_map.end()) { q.type = type_map[qType]; } } else if (itType != it->MemberEnd() && itType->value.IsInt()) { qType = to_string(itType->value.GetInt()); if (type_map.find(qType) != type_map.end()) { q.type = type_map[qType]; } } else { return false; } q.marktype = 0; // 题目类型 auto itMarktype = it->FindMember("marktype"); if (itMarktype != it->MemberEnd() && itMarktype->value.IsInt()){ q.marktype = itMarktype->value.GetInt(); } if (qType == "10")//英文作文 { q.marktype = 10; q.type = 1; } else if (qType == "11")//语文作文 { q.marktype = 4; q.type = 1; } else if (qType == "12")//判断 { q.type = 0; } // 分数 auto itScore = it->FindMember("score"); if (itScore != it->MemberEnd() && itScore->value.IsObject()){ auto itFull = itScore->value.FindMember("full"); if (itFull != itScore->value.MemberEnd() && (itFull->value.IsDouble() || itFull->value.IsInt())) q.score = itFull->value.GetDouble(); else if (itFull != itScore->value.MemberEnd() && itFull->value.IsString()) q.score = atof(itFull->value.GetString()); } // 题目编号 2选做题 auto itId = it->FindMember((q.type == 2 || q.type == 4) ? "editorId" : "id"); if (itId != it->MemberEnd() && itId->value.IsString()){ q.id = itId->value.GetString(); } if (itId != it->MemberEnd() && itId->value.IsInt()){ q.id = std::to_string(itId->value.GetInt()); } if (q.type == 2 || q.type == 4){ auto itAllID = it->FindMember("id"); if (itAllID != it->MemberEnd() && itAllID->value.IsString()){ q.all_id = itAllID->value.GetString(); } } auto itSmallQtNo = it->FindMember("smallQtNo"); if (itSmallQtNo != it->MemberEnd() && !(itSmallQtNo->value.IsNull())) { q.smallQtNo = itSmallQtNo->value.GetInt(); } else { q.smallQtNo = -1; } auto itNickID = it->FindMember("name"); if (itNickID != it->MemberEnd() && !(itNickID->value.IsNull()) && itNickID->value.IsString()) { //m_mapKeguantiNickName[q.id] = itNickID->value.GetString(); } // 打分区域 auto itScoreBox = it->FindMember("scorebox"); if (itScoreBox != it->MemberEnd() && itScoreBox->value.IsObject()){ // 打分框类型 auto itType = itScoreBox->value.FindMember("type"); if (itType != itScoreBox->value.MemberEnd() && itType->value.IsString()){ q.scoreBox.type = std::stoi(itType->value.GetString()); } else if (itType != itScoreBox->value.MemberEnd() && itType->value.IsInt()){ q.scoreBox.type = itType->value.GetInt(); } else{ return false; } if (q.smallQtNo != -1) { // 小问最大分值 auto itmaxScore = itScoreBox->value.FindMember("maxscore"); if (itmaxScore != itScoreBox->value.MemberEnd() && itmaxScore->value.IsString()){ q.scoreBox.maxsorce = std::stod(itmaxScore->value.GetString()); } else if (itmaxScore != itScoreBox->value.MemberEnd() && itmaxScore->value.IsDouble()){ q.scoreBox.maxsorce = itScoreBox->value.GetDouble(); } else if (itmaxScore != itScoreBox->value.MemberEnd() && itmaxScore->value.IsInt()){ q.scoreBox.maxsorce = itmaxScore->value.GetInt(); } else{ q.scoreBox.maxsorce = 0.0; } } else { q.scoreBox.maxsorce = 0.0; } // 分数上限 auto itLimit = itScoreBox->value.FindMember("limit"); if (itLimit != itScoreBox->value.MemberEnd() && itLimit->value.IsString()) q.scoreBox.limit = std::stoi(itLimit->value.GetString()); if (itLimit != itScoreBox->value.MemberEnd() && itLimit->value.IsInt()) q.scoreBox.limit = itLimit->value.GetInt(); // 最后一个格子是否为小数 1是 2否 auto itPoint = itScoreBox->value.FindMember("point"); if (itPoint != itScoreBox->value.MemberEnd()){ if (itPoint->value.IsInt()){ q.scoreBox.bPoint = (itPoint->value.GetInt() == 1); } else if (itPoint->value.IsString()){ std::string str = itPoint->value.GetString(); q.scoreBox.bPoint = (str == "1"); } } // 填空题带打分 if (q.scoreBox.type == 3){ auto itScore = itScoreBox->value.FindMember("Score"); if (itScore != itScoreBox->value.MemberEnd() && itScore->value.IsArray()){ for (auto it = itScore->value.Begin(); it != itScore->value.End(); ++it){ if (it->IsString()){ std::string str = it->GetString(); if (!str.empty()) q.scoreBox.vctScore.push_back(std::stoi(str)); } } } } // 打分位置 auto t = pfGetPos(itScoreBox->value); if (std::get<0>(t)) q.scoreBox.pos = std::get<1>(t); } // 几选几 if (q.type == 2 || q.type == 4){ // 选做题 rapidjson::Value::ConstMemberIterator itSel = it->FindMember("select"); if (itSel != it->MemberEnd() && itSel->value.IsInt()){ q.selItem = itSel->value.GetInt(); } rapidjson::Value::ConstMemberIterator itTotal = it->FindMember("total"); if (itTotal != it->MemberEnd() && itTotal->value.IsInt()){ q.selTotal = itTotal->value.GetInt(); } } // 剪裁区域 if (q.type == 1 || q.type == 3 || q.type == 2 || q.type == 4){ // 1 解答题 2 选做题 3 填空题 auto itCut = it->FindMember("cut"); if (itCut != it->MemberEnd() && itCut->value.IsObject()){ auto itLink = itCut->value.FindMember("linkparm"); if (itLink != itCut->value.MemberEnd() && itLink->value.IsInt()) q.cut.linkparm = itLink->value.GetInt(); if (itLink != itCut->value.MemberEnd() && itLink->value.IsString()) q.cut.linkparm = std::stoi(itLink->value.GetString()); auto t = pfGetPos(itCut->value); if (std::get<0>(t)) q.cut.pos = std::get<1>(t); if (q.type == 3 && m_onlineCardTemplate->subject_id == 8) { TCHAR FilePath[MAX_PATH]; GetModuleFileName(NULL, FilePath, MAX_PATH); (_tcsrchr(FilePath, '\\'))[1] = 0; lstrcat(FilePath, _T("config.ini")); int english = GetPrivateProfileInt(_T("USER"), _T("english_height"), 30, FilePath);//英语填空题高度加大比例 if (english > 0 && english <= 30) { q.cut.pos.h = q.cut.pos.h* (1.0 + english / 100.0); } } } if (q.type == 2){ if (temp_all_id != q.all_id) { temp_all_id = q.all_id; n_duo_xuanti_index = 0; } if (q.cut.linkparm < 2){ std::vector split_qr; split(q.all_id, (std::string)",", &split_qr); if (n_duo_xuanti_index < split_qr.size()) q.id = split_qr[n_duo_xuanti_index++]; } else { std::vector split_qr; split(q.all_id, (std::string)",", &split_qr); if (n_duo_xuanti_index - 1 >= 0 && n_duo_xuanti_index - 1 < split_qr.size()) q.id = split_qr[n_duo_xuanti_index - 1]; } } else if (q.type == 4) { if (temp_all_id != q.all_id) { temp_all_id = q.all_id; n_duo_xuanti_index = 0; } if (q.cut.linkparm < 1){ std::vector split_qr; split(q.all_id, (std::string)",", &split_qr); if (n_duo_xuanti_index < split_qr.size()) q.id = split_qr[n_duo_xuanti_index++]; } else { std::vector split_qr; split(q.all_id, (std::string)",", &split_qr); if (n_duo_xuanti_index - 1 >= 0 && n_duo_xuanti_index - 1 < split_qr.size()) q.id = split_qr[n_duo_xuanti_index - 1]; } } } // 选项 单选题 多选题 if (q.type == 0 || q.type == 8 || q.type == 5){ auto itOpts = it->FindMember("opt"); if (itOpts != it->MemberEnd() && itOpts->value.IsArray()){ for (auto itOpt = itOpts->value.Begin(); itOpt != itOpts->value.End(); ++itOpt){ Opt opt; auto t = pfGetPos(*itOpt); if (std::get<0>(t)) opt.pos = std::get<1>(t); auto itOptName = itOpt->FindMember("optName"); if (itOptName != itOpt->MemberEnd() && itOptName->value.IsString()) opt.optName = itOptName->value.GetString(); q.opt.push_back(opt); } } } else if (q.type == 2 || q.type == 4){ // 选作 auto itSelectqts = it->FindMember("selectqts"); if (itSelectqts != it->MemberEnd() && itSelectqts->value.IsArray() && itSelectqts->value.Size() > 0){ for (auto itOpt = itSelectqts->value.Begin(); itOpt != itSelectqts->value.End(); ++itOpt){ Opt opt; auto t = pfGetPos(*itOpt); if (std::get<0>(t)) opt.pos = std::get<1>(t); auto itOptName = itOpt->FindMember("optName"); if (itOptName != itOpt->MemberEnd() && itOptName->value.IsString()) opt.optName = itOptName->value.GetString(); q.opt.push_back(opt); } } } page.vctQuestions.push_back(q); } } m_onlineCardTemplate->pages.insert(std::make_pair(page.pageNo, page)); } } else{ return false; } } m_onlineCardTemplate->open_save_debug_img = false; m_onlineCardTemplate->dingweidian_range_top = 300; //上定位点范围 m_onlineCardTemplate->dingweidian_rang_buttom = 300;// 下定位点范围 m_onlineCardTemplate->dingweidian_w_max_rate = 1.0; m_onlineCardTemplate->dingweidian_h_max_rate = 1.0; m_onlineCardTemplate->dingweidian_w_min_rate = 0.7; m_onlineCardTemplate->dingweidian_h_min_rate = 0.7; //CString _ini_file = GetExePath() + _T("\\config.ini"); //TCHAR sz_offset_file_name[MAX_PATH] = { 0 }; //GetPrivateProfileString(_T("USER"), _T("offset_file"), _T(""), sz_offset_file_name, sizeof(sz_offset_file_name) / sizeof(TCHAR), _ini_file); //ParseTemplateOffset(UnicodeToAnsi(GetExePath() + _T("\\") + sz_offset_file_name), m_onlineCardTemplate); return true; } void main() { ParseTemplateFromJsonAll("D:\\thirdNanCang\\Win32\\Debug\\1111.zip"); PageIdentify identify; CvMemStorage* storage = cvCreateMemStorage(0); identify.SetTemplate(m_onlineCardTemplate); IplImage *src = cvLoadImage("D:/1测试/1在线南昌全题型/新建文件夹/202112100116_0001.jpg"); IplImage *src2 = cvLoadImage("D:/1测试/1在线南昌全题型/新建文件夹/202112100116_0002.jpg"); IplImage * dst = NULL; IplImage * dst2 = NULL; SchemaPage* pschemaPage1 = NULL; SchemaPage* pschemaPage2 = NULL; std::string path = "D:/1DRAW.jpg"; //LOGI("Identify_impl 1"); bool ret = identify.createSchema(src, &dst, &pschemaPage1, path.c_str(), true, "m_strQrClass", 0); ret = identify.createSchema(src2, &dst2, &pschemaPage2, path.c_str(), true, "m_strQrClass", 0); //LOGI("Identify_impl 2"); OMR_RESULT *m_result_buffer = new OMR_RESULT; identify.out_result = m_result_buffer; identify.omr_result = (identify::result::OMR_RESULT*)identify.out_result; SchemaPage& schemaPage = *pschemaPage1; identify.omr_result->card_qrFlag = schemaPage.qrFlag; identify.omr_result->is_same_exam_id = schemaPage.is_same_exam_id; identify.omr_result->is_front_page = schemaPage.is_front_page; identify.omr_result->is_use_qr_code = schemaPage.is_use_qr_code; identify.omr_result->examid_by_qr_code = schemaPage.examid_by_qr_code; identify.omr_result->strMagicClassId = schemaPage.paper_id; identify.omr_result->strMagicStudentId = schemaPage.student_code; /************************读取学生学号*********************************************/ ret = identify.ReadStudentID(schemaPage, dst); if (ret != identify::result::IDF_SUCCESS) { if (dst != NULL)cvReleaseImage(&dst); if (pschemaPage1 != NULL)delete pschemaPage1; return ; } //LOGI("Identify_impl 3"); /************************查找题目定位点,准备定位数据*********************************************/ ret = identify.FindQuestionLocatePoints(schemaPage, dst); if (ret != identify::result::IDF_SUCCESS) { if (dst != NULL)cvReleaseImage(&dst); cvReleaseMemStorage(&storage); if (pschemaPage1 != NULL)delete pschemaPage1; return ; } /************************客观题()*********************************************/ ret = identify.ReadKeGuanTi(schemaPage, dst); if (ret != identify::result::IDF_SUCCESS) { if (dst != NULL)cvReleaseImage(&dst); cvReleaseMemStorage(&storage); if (pschemaPage1 != NULL)delete pschemaPage1; return ; } //LOGI("Identify_impl 4"); /************************阅卷读取*************************************************/ ret = identify.ReadQuestionScore(schemaPage, dst, storage); if (ret != identify::result::IDF_SUCCESS) { if (dst != NULL)cvReleaseImage(&dst); cvReleaseMemStorage(&storage); if (pschemaPage1 != NULL)delete pschemaPage1; return ; } //LOGI("Identify_impl 6"); /************************根据给定区域切割图片*********************************************/ ret = identify.ClipImg(schemaPage, dst); if (ret != identify::result::IDF_SUCCESS) { if (dst != NULL)cvReleaseImage(&dst); cvReleaseMemStorage(&storage); if (pschemaPage1 != NULL)delete pschemaPage1; return ; } //LOGI("Identify_impl 7"); /************************读取缺考标记*********************************************/ identify.omr_result->quekaoFlag = identify.ReadQuekaoFlag(schemaPage, dst); identify.omr_result->card_index = schemaPage.index; /* if (1){ DrawSchema(dst, pschemaPage); cvSaveImage(path.c_str(), dst); } */ if (dst != NULL)cvReleaseImage(&dst); if (dst2 != NULL)cvReleaseImage(&dst2); cvReleaseMemStorage(&storage); if (pschemaPage1 != NULL)delete pschemaPage1; return ; }