public_define.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. #pragma once
  2. /********************************************************
  3. * @file : public_define.h
  4. * @brief : 公用的定义属性
  5. * @details :
  6. * @author : qqm
  7. * @date : 2021-2-4
  8. *********************************************************/
  9. #include <iostream>
  10. #include <string>
  11. #include <vector>
  12. #include <map>
  13. #include <unordered_map>
  14. #if defined(_MSC_VER) || defined(_WIN32) || defined(_WIN64)
  15. #define dll_export __declspec(dllexport)
  16. #define dll_import __declspec(dllimport)
  17. #else // __linux__
  18. #define dll_export __attribute__ ((visibility("default")))
  19. #include <memory>
  20. #endif
  21. /// dll return value
  22. enum RETURN_VALUE {
  23. RT_OK = 0, /// 正常
  24. RT_ERROR = 1, /// 内部error
  25. RT_UUID_EMPTY = 2, /// 批次号异常
  26. RT_SAVE_PATH_EMPTY = 3, /// 保存路径异常
  27. RT_TEMPLATE_EMPTY = 4, /// 模板为空
  28. RT_HIMGS_LIST_EMPTY = 5, /// 图像列表异常
  29. RT_HIMGS_LIST_NOT_DIV = 6, /// 图像列表不是模板整数被
  30. /// 异常算法新增的异常类型
  31. RT_ERROR_IMAGES_NOT_EQUAL_TPS = 7, /// 传入的答题卡个数跟模板个数不一致
  32. RT_CHECK_ERROR = 8, /// 单份答题卡安全校验未通过
  33. RT_CHECK_LCPTS_NOT_EQUAL_TPS = 9, /// 异常接口2传入的模板定位信息、答题卡定位信息、模板size不相等
  34. RT_CHECK_LCPTINFO_ERROR = 10, /// 传入的定位信息不能满足矫正需求,成对数量<3
  35. RT_CHECK_ONLINECARD_LCPT_ERROR = 11, /// 在线答题卡传入的定位点数量<3
  36. RT_CHECK_LCPTINFO_XS_ERROR = 12, /// 传入的定位信息不能满足矫正需求,分布象限<3
  37. /// 新增模板坐标僬侥
  38. RT_TEMPLATE_BOX_ERROR = 20, /// 模板内的坐标越界或者无效
  39. };
  40. /// debug log leave 主要调式使用
  41. enum LOG_LEAVE{
  42. LOG_AUTO = 0, /// log默认输出,正常接口默认值
  43. LOG_FUN = 1, /// log所有流程中调用的函数 fun_xxx() in! ... fun_xxx() return!
  44. LOG_KEYSTEP = 2, /// log所有的关键点步骤信息
  45. LOG_DETAIL = 3, /// log关键点的具体值各个细节
  46. };
  47. /// 接口参数类型
  48. enum API_PARAM{
  49. TYPE_ONLINE_CARD = 1, /// 在线答题卡
  50. TYPE_THRID_CARD = 2, /// 第三方答题卡
  51. NEED_OCR_SOCRE = 4, /// 需要识别分数
  52. NO_NEED_OCR_SCORE= 8, /// 不需要识别分数
  53. ERROR_CARD = 16, /// 异常答题卡 api_processing_error_images_hand 接口使用
  54. };
  55. /// 答题卡类型
  56. enum CARD_TYPE {
  57. OLWS = TYPE_ONLINE_CARD | NEED_OCR_SOCRE, /// 在线 识别分数
  58. OLNS = TYPE_ONLINE_CARD | NO_NEED_OCR_SCORE, /// 在线 不识别分数
  59. TDWS = TYPE_THRID_CARD | NEED_OCR_SOCRE, /// 第三方 识别分数
  60. TDNS = TYPE_THRID_CARD | NO_NEED_OCR_SCORE, /// 第三方 不识别分数
  61. OLWSE = OLWS | ERROR_CARD, /// api_processing_error_images_hand接口类型
  62. OLNSE = OLNS | ERROR_CARD,
  63. TDWSE = TDWS | ERROR_CARD,
  64. TDNSE = TDNS | ERROR_CARD,
  65. };
  66. /// 答题卡可能的状态信息 !!!有待完善设计
  67. enum PAPER_STATUS {
  68. PAPER_SUCC = 0, /// SUCC
  69. MISSED_LOCATION_POINT = 1, /// 定位点缺失
  70. MISSED_LOCATION_AREA = 2, /// 定位区缺失
  71. MISSED_LOCATION_CROSSPOINT = 4, /// 交叉点缺失
  72. MATCH_FAILED = 8, /// 分页失败 模板不匹配
  73. PROGRAM_ERROR = 16,/// 程序异常导致的失败
  74. PAGEDISMISS = 32,/// 本份缺页
  75. PAGEDATAERROR = 64,/// 本份图像异常
  76. };
  77. namespace preinfo {
  78. /// 图像方向 逆时针方向
  79. enum IMG_ROTATION {
  80. ROTATION_0 = 1,
  81. ROTATION_90 = 2,
  82. ROTATION_180 = 4,
  83. ROTATION_270 = 8,
  84. };
  85. /// 图像&试题类型
  86. enum BOX_TYPE
  87. {
  88. BOX_NONE, /// UNKNOW
  89. BOX_ABSENCE_MARK, /// 缺考标记
  90. BOX_BREAK_PRECEDENT, /// 违纪标记
  91. BOX_EXAM_TT_NUMBER, /// 填涂考号
  92. BOX_EXAM_QRCODE, /// 试卷二维码
  93. BOX_EXAM_BARCODE, /// 试卷条码
  94. BOX_QUESTION_CHOICE_S, /// 单项选择题
  95. BOX_QUESTION_CHOICE_M, /// 不定项选择题
  96. BOX_QUESTION_COMPLETION,/// 填空题
  97. BOX_QUESETION_TF, /// 判断题
  98. BOX_SUBJECTIVE_NORMAL, /// 普通主观题
  99. BOX_SCORING_BOX, /// 线下阅卷的打分区
  100. BOX_SUBJECTIVE_CHOOSE, /// 选做题
  101. BOX_SUBJECTIVE_CHOOSE_COMBIN, /// 选做题-合并填涂
  102. BOX_SUBJECTIVE_CHOOSE_SPLITE, /// 选做题-分离填涂
  103. BOX_WRITE_CHINESE_COMPOSITION, /// 写作-语文作文
  104. BOX_WRITE_ENGLISH_WRITING, /// 写作-英语写作
  105. BOX_LOCATION_POINT, /// 定位点
  106. BOX_LOCATION_AREA, /// 定位区
  107. BOX_LOCATION_CROSS, /// 定位交叉点
  108. };
  109. /// 方向
  110. enum DIR_FLAG {
  111. DIR_UNKNOW = -1,
  112. DIR_UP = 1,
  113. DIR_DOWN = 2,
  114. DIR_LEFT = 4,
  115. DIR_RIGHT = 8
  116. };
  117. /// 填涂区域的方向
  118. enum TT_DIR_FLAG {
  119. TT_Y = 0, /// 垂直
  120. TT_X = 1, /// 水平
  121. };
  122. template<typename T> struct TtSize{ ///
  123. T width;
  124. T height;
  125. TtSize() :width(T(0)), height(T(0)) {};
  126. };
  127. template<typename T> struct PaperRect {
  128. T centerx;
  129. T centery;
  130. T width;
  131. T height;
  132. T getX() const { return centerx - width / 2.0;}
  133. T getY() const { return centery - height/ 2.0; }
  134. PaperRect() :centerx(T(-1)), centery(T(-1)), width(T(0)), height(T(0)) {};
  135. };
  136. struct Field :PaperRect<double> {
  137. int id; /// 一个唯一标识符 不可能有重复的
  138. std::vector<int> vecTiHao; /// 整数题号 可以有重复
  139. Field() :id(-1) {};
  140. };
  141. /// 定位点
  142. struct LocationPoint :Field {
  143. BOX_TYPE type;
  144. LocationPoint() :type(BOX_LOCATION_POINT) {};
  145. };
  146. /// 定位区
  147. struct LocationArea :Field {
  148. BOX_TYPE type;
  149. bool head; /// 是否是试卷名称区域
  150. LocationArea() :head(false), type(BOX_LOCATION_AREA) {};
  151. };
  152. /// 交叉点
  153. struct LocationCrossPoint :Field {
  154. BOX_TYPE type;
  155. int sign; /// 交叉点开口方向
  156. double angle;
  157. LocationCrossPoint() :sign(DIR_UNKNOW), angle(0.0), type(BOX_LOCATION_CROSS) {};
  158. };
  159. /// 条码/二维码
  160. struct CodeInfo :Field {
  161. BOX_TYPE type; /// BOX_EXAM_QRCODE or BOX_EXAM_BARCODE
  162. TT_DIR_FLAG way;
  163. CodeInfo() :type(BOX_EXAM_BARCODE), way(TT_X) {};
  164. };
  165. /// 缺考标记
  166. struct AbsenceMark:Field {
  167. BOX_TYPE type;
  168. AbsenceMark() :type(BOX_ABSENCE_MARK) {};
  169. };
  170. /// 填涂考号
  171. struct FillStuNumber:Field {
  172. bool useable; /// 是否可用
  173. TT_DIR_FLAG way; /// 水平/垂直
  174. int cols; /// 列数
  175. int rows; /// 行数
  176. TtSize<double> itemSize; /// 单个小项宽高
  177. double disx; /// 横向相邻的两个小项的x坐标的距离差
  178. double disy; /// 纵向的........
  179. FillStuNumber() :useable(false), way(TT_Y), cols(-1), rows(-1), disx(0.0), disy(0.0) {};
  180. void init_dis() {
  181. disx = (cols == 1) ? 0.0 : (width - itemSize.width) * 1.0 / (cols - 1) * 1.0;
  182. disy = (rows == 1) ? 0.0 : (height - itemSize.height) * 1.0 / (rows - 1) * 1.0;
  183. }
  184. };
  185. /// 填涂考号 拆解到小项坐标
  186. /// 填涂小项结构信息
  187. struct TtItem :PaperRect<double> {
  188. std::string optName; /// 0 ~ 9 A B C D .... 填涂
  189. };
  190. /// 新逻辑 - 填涂考号
  191. struct _FillStuNumber{
  192. bool useable; /// 是否可用
  193. int cols; /// 列数
  194. int rows; /// 行数
  195. std::map<int,std::vector<TtItem>> groups; /// pair<列序号(0开始),小项合集(从上到下)>
  196. _FillStuNumber() : useable(false), cols(-1), rows(-1) { groups.clear(); };
  197. };
  198. /// 新逻辑 - 填涂选做题 or 选择题
  199. struct _QuestionChoice:Field{
  200. BOX_TYPE type; /// BOX_QUESTION_CHOICE_S / M
  201. int number; /// 填涂个数
  202. TT_DIR_FLAG way; /// 方向
  203. TtSize<double> itemSize; /// 单个小项宽高
  204. std::vector<TtItem> groups; /// 组内的各个小项
  205. _QuestionChoice():number(0),way(TT_X) {};
  206. };
  207. /// 判断题
  208. struct QuesetionTF:Field{
  209. ;
  210. };
  211. /// 单个选择题
  212. struct QuestionChoice:Field{
  213. BOX_TYPE type; /// BOX_QUESTION_CHOICE_S / M
  214. TT_DIR_FLAG way; /// 水平/垂直
  215. TtSize<double> itemSize; /// 单个小项宽高
  216. int number; /// 填涂项个数
  217. std::vector<TtItem> groups; /// 组内的各个小项
  218. QuestionChoice() :type(BOX_QUESTION_CHOICE_M), way(TT_X), number(0) {};
  219. };
  220. /// 主观题的区域信息
  221. struct SubjectiveField:Field{
  222. BOX_TYPE type;
  223. bool multiple; /// 是否多块
  224. int orderNumber; /// 如果是多块 本块序号 从1开始
  225. bool needConbin; /// 是否需要合并一起
  226. int marktype; /// 如果等于4或者10则需要保留小图 2021.6.11 确认如果试题 如此切图
  227. TT_DIR_FLAG way; /// 左右拼接 or 上下拼接
  228. std::string name; /// 落地保存的文件名 e: "17" "22"
  229. SubjectiveField() :type(BOX_SUBJECTIVE_NORMAL), multiple(false), orderNumber(1), needConbin(true), way(TT_Y), name("") {};
  230. };
  231. /// 打分区
  232. enum SCORE_TYPE {
  233. NONE = 0, ///
  234. NORMAL = 1, /// 一般的
  235. COMBIN = 2, /// 组合型 个位&十位
  236. QtCom = 3, /// 填空题
  237. };
  238. struct SocringArea:PaperRect<double> { /// 关联在 boxInfo下面 多块的只有ordernumber=0需要识别分数
  239. bool ocr; /// 是否需要识别分数
  240. int cols; /// 列数
  241. SCORE_TYPE type;
  242. bool withHalf; /// 是否含有.5分
  243. int limit; /// 上限分值
  244. double maxSocre; /// 小问最大分值
  245. std::vector<double> vecSocreValue; /// 每个格子对应的数据 小于零的项不可用(个位&十位格子)
  246. SocringArea() :cols(0), type(NONE),withHalf(false),ocr(false),limit(-1), maxSocre(-1.0){};
  247. };
  248. /// 单个填空题
  249. struct QuestionCompletion :SubjectiveField {
  250. SocringArea scoreBox;
  251. };
  252. /// 其他类型的box 只需要切割区域不需要额外操作的
  253. struct BoxInfo :SubjectiveField {
  254. SocringArea scoreBox;
  255. BoxInfo() {};
  256. };
  257. /// 选做题的标识符 每个选做题&选做题填涂 都有唯一的Key
  258. struct SubjectiveChooseKey {
  259. std::vector<int> vecIds; /// 选做题的id列表
  260. std::vector<std::string> vecNames; /// 别名列表
  261. int idx; /// 本块的序号 0 1 2 3 ...多选多的N序号
  262. bool hbtt; /// 是否是合并填涂
  263. int m; /// m选n
  264. int n; /// m选n
  265. bool operator == (const SubjectiveChooseKey & _k) {
  266. return (_k.vecIds == vecIds) && (_k.idx == idx);
  267. }
  268. SubjectiveChooseKey() :idx(-1),hbtt(true) {};
  269. };
  270. /// 选做题的区域信息
  271. struct SubjectiveChooseField:SubjectiveField{
  272. SubjectiveChooseKey key;
  273. SocringArea scoreBox;
  274. };
  275. /// 选做题的填涂判断信息
  276. struct SubjectiveChooseTt:QuestionChoice{
  277. SubjectiveChooseKey key;
  278. };
  279. /// 新逻辑的填涂信息
  280. struct _SubjectiveChooseTt : _QuestionChoice {
  281. SubjectiveChooseKey key;
  282. };
  283. /// 待定...
  284. struct SubjectiveChoose { /// 选做题 分离&合并填涂 M选N
  285. int m; /// 总数
  286. int n; /// 选做个数
  287. std::vector<int> ids; /// 题号列表
  288. std::vector<SubjectiveChooseField> vecBoxes; /// 图像区域列表
  289. std::vector<SubjectiveChooseTt> vecTt; /// 填涂区域列表
  290. virtual void push_back(const SubjectiveField & sjtField) = 0;
  291. };
  292. struct Combin:public SubjectiveChoose{ /// 合并填涂
  293. };
  294. struct Splite:public SubjectiveChoose{ /// 分离填涂
  295. Splite(const int & _m, const int & _n) {
  296. ;
  297. }
  298. protected:
  299. };
  300. /// 答题卡模板
  301. typedef struct PaperTemplateInfo {
  302. int index; /// 模板页的序号 从0开始
  303. int width; ///
  304. int height; ///
  305. std::string strJsonPath; /// 模板json文件绝对路径
  306. std::string strImgPath; /// 本张模板图像路径/URL
  307. std::vector<BoxInfo> vecBoxes; /// 本张模板内主观题题目信息
  308. std::vector<LocationPoint> vecLocaltionPoints; /// 定位点信息
  309. std::vector<LocationArea> vecLocaltionAreas; /// 定位区信息
  310. std::vector<LocationCrossPoint> vecLocationCross; /// 交叉点信息
  311. std::vector<QuestionChoice> vecQtChoices; /// 选择题
  312. std::vector<_QuestionChoice> _vecQtChoices; /// _选择题
  313. std::vector<QuesetionTF> vecQtTf; /// 判断题
  314. std::vector<QuestionCompletion> vecQtCompletion; /// 填空题
  315. std::vector<AbsenceMark> vecAbsenceMark; /// 缺考&违纪
  316. std::vector<CodeInfo> vecCodeBQ; /// 条码/ 二维码
  317. std::vector<FillStuNumber> vecFillNumber; /// 填涂考号
  318. std::vector<_FillStuNumber> _vecFillNumber; /// _填涂考号
  319. std::vector<SubjectiveChooseField> vecXzBoxes; /// 选做题题目信息
  320. std::vector<SubjectiveChooseTt> vecXzTtBoxes; /// 选做题填涂信息
  321. std::vector<_SubjectiveChooseTt> _vecXzTtBoxes; /// 选做题填涂信息
  322. void * ptrAreaFeatures; /// 定位区特征
  323. } ptinfo;
  324. typedef std::vector<PaperTemplateInfo> templatesInfo;
  325. /// 选做题信息
  326. struct XX {
  327. std::vector<int> vecTiHao; ///! 必须是按照题号 升序排列
  328. int m;
  329. int n;
  330. /**
  331. 2022.1.19 题组实现逻辑
  332. 问题:题组的结构是数量的N倍,与现有的逻辑冲突,但是如果把题组的题号拆分成两个
  333. 选做题就可以实现,但是问题就是 第二块没有填涂区域,如何解决这个问题 ,
  334. 方案:
  335. 设定一个标识 判断是否使用其他题号的填涂判断结果
  336. stealVecRes = true 则本题偷取 vecStealTiHao 的填涂结果
  337. */
  338. bool stealVecRes;
  339. std::vector<int> vecStealTiHao;
  340. XX() :m(0), n(0), stealVecRes(false) { vecStealTiHao.clear(); };
  341. };
  342. struct SubjChiInfo {
  343. bool hasSplitTT;
  344. bool hasCombinTT;
  345. std::vector<XX> vecSptt;
  346. std::vector<XX> vecCbtt;
  347. SubjChiInfo() :hasSplitTT(false), hasCombinTT(false) {};
  348. };
  349. struct QtNumInfo {
  350. std::vector<int> qtIds;
  351. int qtNum;
  352. };
  353. }
  354. namespace analysis {
  355. /// 记录定位点 定位区 交叉点的查找情况
  356. struct LocationResult
  357. {
  358. std::vector<preinfo::LocationPoint> vecLcpts; /// 图像找到的定位点
  359. std::vector<preinfo::LocationArea> vecAreas; /// 图像找到的上的定位区
  360. std::vector<preinfo::LocationCrossPoint> vecCrosses;/// 图像找到的上的交叉点
  361. LocationResult() { vecLcpts.clear(); vecAreas.clear(); vecCrosses.clear(); }
  362. };
  363. /// 每张答题卡的匹配结果
  364. struct MatchResult {
  365. bool matched; /// 是否匹配到了
  366. PAPER_STATUS matchedStatus; /// 匹配过程中的状态记录
  367. int matchedCount; /// 匹配到点数
  368. int totalCount; /// 参与匹配的总数
  369. int schemaIndex; /// 匹配到模板ID 从0开始
  370. double scale; /// 与模板的比例系数
  371. int dir; /// 方向
  372. LocationResult lcRes; /// 定位信息结果
  373. double transfrom[6]; /// 第三方的3*2矫正举证 模板-图像
  374. double transfrom_[6]; /// 在线&第三方的3*2举证 图像-模板
  375. bool nineUse; /// 是否优先使用3*3矩阵
  376. double olctransfrom_[9]; /// 在线答题卡的3*3映射矩阵 图像-模板
  377. MatchResult() { nineUse = false; matched = false; matchedStatus = PAPER_SUCC; matchedCount = 0; totalCount = 0; schemaIndex = -1; scale = -1; dir = 0; }
  378. };
  379. struct PageRes {
  380. int idx;
  381. preinfo::DIR_FLAG dir;
  382. PageRes() { idx = -1; dir = preinfo::DIR_UNKNOW; }
  383. };
  384. }
  385. namespace result {
  386. /**
  387. !所有填涂判断的起始值都是 -1 标识未填涂
  388. */
  389. enum ABSENT_MARK {
  390. MARK_NORMAL = 0, /// 正常
  391. MARK_ABSENCE = 1, /// 缺考
  392. MARK_BREAK_PRECEDENT =2, /// 违纪
  393. CHOICE_TOO_MUCH = 4, /// 单选题 填涂了全部
  394. CHOICE_NONE = 8, /// 本题未填涂
  395. };
  396. /// 填涂题目结果
  397. struct ChoiceResult {
  398. struct element {
  399. int index; /// 按照从左到右/从上到下排列小项的下标 从-1开始 标识未填涂
  400. double confidence; /// 置信度
  401. element() :index(-1), confidence(0.0) {};
  402. };
  403. int id; /// 与模板的ID对应
  404. int tiHao; /// 题号
  405. ABSENT_MARK status; /// 本题的状态
  406. int number; /// 本题小项个数
  407. int mostCredible; /// 单选情况下 最可信的ID下标
  408. std::vector<std::string> vecOpts; /// 本题结果选项是哪一个
  409. preinfo::BOX_TYPE type; /// 多选还是单选
  410. std::vector<bool> vecRes;/// _看需求 是否启用 true:填涂了 false:未填涂
  411. std::vector<element> vecIdx;/// 备选方案
  412. ChoiceResult() :id(-1),tiHao(-1), status(MARK_NORMAL), number(0), type(preinfo::BOX_QUESTION_CHOICE_M) {};
  413. };
  414. /// 判断题
  415. struct QTFRes {
  416. int id;
  417. bool fill;
  418. QTFRes() :id(-1), fill(false) {};
  419. };
  420. /// 主观题题目
  421. struct SubjectiveResult {
  422. struct IMG_INFO {
  423. std::vector<unsigned char> imgData;
  424. bool vaild;
  425. int cols;
  426. int rows;
  427. int channel;
  428. IMG_INFO() :vaild(false), cols(0), rows(0), channel(0) {};
  429. };
  430. int id; /// 不是题号 是一个UUID雷士的东西
  431. std::vector<int> uuids; /// 多块合并的图像,是可能有多个UUID的 2022.1.19 新增
  432. int th; /// 本题的题号
  433. std::vector<int> tiHao; /// 选做题适用
  434. bool multiple; /// 是否多块
  435. int orderNumber; /// 如果是多块 本块序号 默认从1开始 如果是合并得到图则 ordernumber=-1
  436. double score; /// 分数
  437. preinfo::BOX_TYPE type; /// BOX TYPE
  438. int marktype; /// 是否保存分块的小图 只有4和10保留
  439. int idx; /// 只有type=选做题时候有效
  440. IMG_INFO img; /// 线下阅卷问题 预留方案
  441. /*
  442. 2022.1.19 改动 多个小块的图像有可能有多个打分框 所以要做支持
  443. 改动记录:
  444. 由 vector<int> 改动到 unordered_map<int, std::vector<int>> ,int = uuid 作为唯一关联key值
  445. **/
  446. std::vector<int> sr; /// 分数判断结果 内容:红色批改的框的红色值 个数:所有小框数量和
  447. std::unordered_map<int, std::vector<int>> mapSr; /// 记录每个uuid对应的打分框的识别结果
  448. std::string path; /// 绝对路径
  449. std::string name; /// 落地文件名
  450. int width; /// 2021.4.24 需求需要提供主观题的宽高信息
  451. int height; /// ...
  452. SubjectiveResult() :id(-1), multiple(false), orderNumber(1),marktype(0),
  453. score(0.0),idx(-1), type(preinfo::BOX_NONE), path(""), name(""), width(0),height(0) {};
  454. };
  455. /// 选做题
  456. struct SubjectiveChooseResult{
  457. preinfo::SubjectiveChooseKey key;
  458. preinfo::BOX_TYPE type;
  459. int id;
  460. int tIdx; /// 选中的下标 0:可能是未填涂默认值 也有可能是填涂了第一个
  461. std::string path; /// 绝对路径
  462. std::string name; /// 文件名
  463. double score; /// 分数
  464. SubjectiveChooseResult() :type(preinfo::BOX_SUBJECTIVE_CHOOSE), id(-1), tIdx(-1), path(""), name(""), score(0.0) {};
  465. };
  466. /// 选做题结果简单记录
  467. struct SubjChResRecord {
  468. std::vector<int> vecTiHaos;
  469. int m; int n;
  470. preinfo::BOX_TYPE type;
  471. std::vector<int> vecRes;
  472. };
  473. /// 识别的单份答题卡结果
  474. typedef struct SinglePaperInfo {
  475. int orderNumber; /// 本份的序号 备注:orderNumber = totalNumbers/mb.size()
  476. bool last; /// 是否本批次最后一份
  477. int idx; /// 如果状态是异常,标明那一张答题卡出现了异常,下标0开始 备注:首先判断status的状态
  478. int numbers; /// 本份页数 备注:理论上等于模板的张数
  479. int choiceNumbers; /// 所有填涂题目个数 备注:所有选择题总数量
  480. PAPER_STATUS status; /// 本份试卷状态标志 备注:见枚举定义
  481. ABSENT_MARK absent; /// 缺考 or 违纪 备注:见枚举定义
  482. std::string barCode; /// 条码识别结果 备注:条形码识别结果 仅仅是条形码结果
  483. std::string qrCode; /// 二维码识别结果 备注:二维码识别结果 空值只能标明未识别到或者没有条码 条码也适用
  484. std::string fillNumber; /// 填涂考号 备注:长度=模板设定考号列数,未填涂位置用' '空格填充 !!!重要
  485. std::string strSavePath; /// 本份的保存路径 备注:备份的保存路径下面会有 xx.jpg xx_.jpg等等图像
  486. std::vector<std::string> vecUrlPath; /// 图像的本地路径 备注:客户端需求添加
  487. std::vector<std::string> vecUrlAPath; /// 矫正后的原图路径 备注:矫正后的图,顺序为 img_1.jpg img_2.jpg ... 不超过模板张数
  488. std::vector<QTFRes> tfRes; /// 判断题 备注:该类型未实现
  489. std::vector<ChoiceResult> choiceRes; /// 所有填涂题目结果 备注:使用tiHao(int) 和 vecOpts(判断结果)即可 ,单选题vecOpts可能是一个或者全部数量(对应全部填涂错误)多选择是真实个数
  490. std::shared_ptr<ChoiceResult> ptrChoiceRes; /// 所有填涂题目结果 备注:未启用 请忽略
  491. std::vector<SubjectiveResult> subjectiveRes; /// 主观题 备注:所有主观题(填空,解答,选做等等)都在这里面 th标识本题最终输出结果
  492. std::shared_ptr<SubjectiveResult> ptrSubjective; /// ...... 备注:未启用 请忽略
  493. std::vector<SubjChResRecord> subjectiveCRes; /// 选做题 备注:存放选择题判断结果 内部使用请忽略
  494. std::shared_ptr<SubjChResRecord> ptrSubjectiveC; /// 备注:未启用 请忽略
  495. std::vector<analysis::LocationResult> vecLcRes; /// 定位信息的结果保存 备注:与 vecUrlPath 一一对应
  496. SinglePaperInfo() :orderNumber(-1), last(false), idx(-1), numbers(0), choiceNumbers(0), status(PAPER_SUCC), absent(MARK_NORMAL),
  497. barCode(""), qrCode(""), fillNumber(""), strSavePath("") {};
  498. }spinfo;
  499. }