schema_struct.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. #pragma once
  2. #include <string>
  3. #include <opencv2/opencv.hpp>
  4. #include <vector>
  5. using namespace cv;
  6. using namespace std;
  7. namespace identify{
  8. namespace {
  9. enum OMR_QUESTION_TYPE{
  10. DANXUANTI,
  11. DUOXUANTI,
  12. TIANKONGTI,
  13. ZHUTUANTI,
  14. TIANKONGTI2,// 带分数
  15. XUANZUOTI, // 选做题
  16. DUOXUANTIEX, // 不定项
  17. };
  18. }
  19. namespace analysis{
  20. struct SAMPLE_KEGUANTITUDIAN{
  21. //涂黑相对面积
  22. float BlackRefArea;
  23. //黑色区域高黑度相对面积
  24. float HighBlackRefArea;
  25. //黑色区域低黑度相对面积
  26. float LowBlackRefArea;
  27. //模糊度
  28. float Blur;
  29. //涂黑区域平均灰度
  30. float RefAvgGray;
  31. //当前组的最大涂黑相对面积
  32. float MaxBlackRefArea;
  33. //当前组的最小涂黑相对面积
  34. float MinBlackRefArea;
  35. //同组最大高黑度区域相对面积
  36. float MaxHighBlackRefArea;
  37. //同组最小平均灰度
  38. float MinRefAvgGray;
  39. };
  40. /*匹配结果*/
  41. struct MATCH_REUSLT{
  42. MATCH_REUSLT(){ matched = false; matched_count = 0; total_count = 0; schema_index = -1; scale = -1; dir = 0; }
  43. bool matched;
  44. int matched_count;
  45. int total_count;
  46. int schema_index;
  47. double scale;
  48. int dir;
  49. double transfrom[6];
  50. };
  51. }
  52. namespace schema{
  53. //旋转角 枚举各旋转角(逆时针旋转 0度,90度,180度,270度)
  54. enum ISCH_ROTATION{
  55. //逆时针旋转 0度
  56. ROTATION_0 = 1,
  57. //逆时针旋转 90度
  58. ROTATION_90 = 2,
  59. //逆时针旋转 180度
  60. ROTATION_180 = 4,
  61. //逆时针旋转 270度
  62. ROTATION_270 = 8
  63. };
  64. //方向标记
  65. enum ISCH_DIR_FLAG{
  66. DIR_FLAG_UP = 1,
  67. DIR_FLAG_DOWN = 2,
  68. DIR_FLAG_LEFT = 4,
  69. DIR_FLAG_RIGHT = 8
  70. };
  71. template<typename T>struct ISCH_SCHEMA_RECT_FIELD{
  72. T centerx;
  73. T centery;
  74. T width;
  75. T height;
  76. };
  77. struct ISCH_SCHEMA_ELEMENT_FIELD :ISCH_SCHEMA_RECT_FIELD<float>{
  78. int nID;
  79. };
  80. struct ISCH_SCHEMA_LOCATE_POINT :ISCH_SCHEMA_ELEMENT_FIELD{//定位点
  81. };
  82. struct ISCH_SCHEMA_LOCATE_AREA :ISCH_SCHEMA_ELEMENT_FIELD{//区域定位点
  83. };
  84. enum ISCH_SCHEMA_CROSS_SIGN_FLAG{
  85. //表示向上的边
  86. ISCH_SCHEMA_CROSS_SIGN_UP = 1,
  87. //表示向下的边
  88. ISCH_SCHEMA_CROSS_SIGN_DOWN = 2,
  89. //表示向左的边
  90. ISCH_SCHEMA_CROSS_SIGN_LEFT = 4,
  91. //表示向右的边
  92. ISCH_SCHEMA_CROSS_SIGN_RIGHT = 8,
  93. };
  94. struct ISCH_SCHEMA_LOACTE_CROSS :ISCH_SCHEMA_ELEMENT_FIELD{//交叉点定位
  95. int sign;
  96. double angle;
  97. };
  98. enum ISCH_DIRECTION{
  99. Horizontal,
  100. Vertical,
  101. DIR_UNKNOWN,
  102. };
  103. struct ISCH_SCHEMA_CODE :ISCH_SCHEMA_ELEMENT_FIELD{//条码、二维码
  104. ISCH_DIRECTION bDirection;
  105. };
  106. struct ISCH_SCHEMA_ITEM :ISCH_SCHEMA_ELEMENT_FIELD{//填涂项
  107. //填涂项输出字符
  108. char OutChar[128];
  109. int nGroupID;
  110. int nMatrixID;
  111. int keguanti_question_locate_point_index;
  112. };
  113. enum ISCH_OUT_TYPE_FLAG{
  114. OTF_SINGLE = 1,
  115. OTF_MUTIL = 1 << 1,
  116. OTF_STRICT = 1 << 3,
  117. OTF_NONSTRICT = 1 << 4,
  118. OTF_NONSTRICT_ERROR = 1 << 5,
  119. };
  120. //客观题输出类型
  121. enum ISCH_OMR_OUT_TYPE{
  122. // 输出一个或*号,若解析中有0个、2个或2个以上涂点被填涂,输出*号
  123. OMR_OUT_TYPE_SINGLE_NONSTRICT_ERROR = OTF_SINGLE | OTF_NONSTRICT_ERROR,
  124. // 输出一个,若解析中有2个或2个以上涂点被填涂,则从中选出一个作为该组结果
  125. OMR_OUT_TYPE_SINGLE_NONSTRICT = OTF_SINGLE | OTF_NONSTRICT,
  126. // 输出一个,若解析中有2个或2个以上涂点被填涂,则认为用户多选,输出多选字符
  127. OMR_OUT_TYPE_SINGLE_STRICT = OTF_SINGLE | OTF_STRICT,
  128. // 输出多选字符
  129. OMR_OUT_TYPE_MUTIL_STRICT = OTF_MUTIL | OTF_STRICT,
  130. };
  131. struct ISCH_QUESTION_BASIC{
  132. std::string question_code;
  133. int question_index;
  134. };
  135. enum ISCH_QUESTION_TYPE_FLAG{
  136. //单选题
  137. QTF_DANXUANTI = 1,
  138. //多选
  139. QTF_DUOXUANTI = 2,
  140. //判断题
  141. QTF_PANDUANTI = 3,
  142. //填空题
  143. QTF_TIANKONGTI = 4,
  144. //主观题
  145. QTF_ZHUGUANTI = 5,
  146. //是否是选做题标记位
  147. QTF_XUANZUOTI = 0x100,
  148. //是否是客观题标记为
  149. QTF_XUANZE = 0x200,
  150. //题型蒙版
  151. QTF_QUESTION_TYPE_MASK = 0xff,
  152. };
  153. struct ISCH_SCHEMA_GROUP :ISCH_SCHEMA_ELEMENT_FIELD{//填涂组
  154. //本组涂点涂点数量
  155. int itemCount;
  156. int nMatrixID;
  157. //OMR 输出类型
  158. ISCH_OMR_OUT_TYPE omr_out_type;
  159. };
  160. struct ISCH_SCHEMA_CLIP :ISCH_SCHEMA_ELEMENT_FIELD{//切割区域
  161. //裁切区域名称
  162. std::string area_name;
  163. int markUnit;
  164. //该区域对应的切块的第几块(从1开始)
  165. int markUnitPart;
  166. std::string area_name_by_questionNo;
  167. };
  168. enum class GROUP_TYPE
  169. {
  170. NONE,
  171. TIANTUKAOHAO,
  172. KEGUANTI,
  173. QUEKAO,
  174. XUANZUOTI,
  175. };
  176. struct ISCH_IDENTIFY_GROUP :ISCH_SCHEMA_GROUP{
  177. std::vector<int> itemIndex;
  178. GROUP_TYPE group_type;
  179. };
  180. struct ISCH_IDENTIFY_AREA{
  181. ISCH_SCHEMA_LOCATE_AREA locate_area;
  182. std::vector<KeyPoint> locateAreasKeyPoints;
  183. cv::Mat locateAreasDescriptor;
  184. CvPoint locateAreasOffset;
  185. };
  186. struct ISCH_SCHEMA_ZHUGUANTI :ISCH_SCHEMA_ELEMENT_FIELD, ISCH_QUESTION_BASIC{//题目分数
  187. std::vector<ISCH_SCHEMA_ELEMENT_FIELD> options;
  188. //有效评分框数量(题目总分较小,无需所有评分框)
  189. int valid_option_count;
  190. };
  191. struct ISCH_SCHEMA_TIANKONGTI :ISCH_SCHEMA_ELEMENT_FIELD, ISCH_QUESTION_BASIC{//题目分数
  192. ISCH_SCHEMA_ELEMENT_FIELD option;
  193. };
  194. class ISCH_SCHEMA_PAGE{
  195. public:
  196. ISCH_SCHEMA_PAGE(){
  197. index = -1;
  198. option_spacer = ',';
  199. hei_du_ling_min_du = 4;
  200. width = -1;
  201. height = -1;
  202. }
  203. //从0开始的试卷页码序号
  204. int index;
  205. //模板图像宽度
  206. int width;
  207. //模板图像高度
  208. int height;
  209. std::vector<ISCH_SCHEMA_LOCATE_POINT> locatePoints;
  210. std::vector<ISCH_SCHEMA_LOACTE_CROSS> locateCrosses;
  211. std::vector<ISCH_IDENTIFY_AREA> locateAreas;
  212. std::vector<ISCH_IDENTIFY_AREA> assistLocateArea;
  213. std::vector<ISCH_SCHEMA_CODE> codes;
  214. std::vector<ISCH_IDENTIFY_GROUP> groups;
  215. std::vector<ISCH_SCHEMA_ITEM> items;
  216. std::vector<ISCH_SCHEMA_CLIP> cutAreas;
  217. std::vector<ISCH_SCHEMA_TIANKONGTI> tiankongtis;
  218. std::vector<ISCH_SCHEMA_ZHUGUANTI> zhuguantis;
  219. //多个选项之间的间隔字符
  220. char option_spacer;
  221. //黑度灵敏度
  222. int hei_du_ling_min_du;
  223. };
  224. typedef std::vector<ISCH_SCHEMA_PAGE> ISCH_Schema;
  225. }
  226. namespace result{
  227. //识别结果
  228. enum IDENDTIFY_RESULT{
  229. //成功
  230. IDF_SUCCESS,
  231. //失败
  232. IDF_FAILURE,
  233. //创建模板--失败
  234. IDF_TEMPLATE_FAILURE,
  235. //创建模板--没有找到足够的定位点
  236. IDF_TEMPLATE_NOTFOUND_ENOUGH_LOCATEPOINT,
  237. //创建模板--无法找到内容结束位置
  238. IDF_TEMPLATE_NOTFOUNDBOTTOM,
  239. //创建模板--试卷二维码非法
  240. IDF_TEMPLATE_QRCODE_ILLEGAL,
  241. //无法添加模板,模板已被锁定,不能再增加
  242. IDF_TEMPLATE_LOCKED,
  243. //无法添加模板,模板重复
  244. IDF_TEMPLATE_REPEAT,
  245. //没有找到足够的定位点
  246. IDF_NOTFOUND_ENOUGH_LOCATEPOINT,
  247. //无法匹配模板
  248. IDF_CANNOT_MATCH_TEMPLATE,
  249. //二维码解析失败
  250. IDF_PRASE_QR_ERROR,
  251. //没有模板
  252. IDF_MISSING_TEMPLATES,
  253. //图像太小
  254. IDF_SIZE2SMALL,
  255. //边长比例与模板不符
  256. IDF_SIDERATIO,
  257. //除数为零
  258. IDF_DIVIDE_ZERO,
  259. ERR_MEM_UNENOUGH,
  260. };
  261. enum OMR_QUESTION_STATE{
  262. //正常
  263. OMR_QUESTION_STATE_NORMAL,
  264. //多涂
  265. OMR_QUESTION_STATE_DUOTU,
  266. //漏涂
  267. OMR_QUESTION_STATE_LOUTU,
  268. //漏批
  269. OMR_QUESTION_STATE_LOUPI,
  270. //无法识别
  271. OMR_QUESTION_STATE_WUFASHIBIE
  272. };
  273. //对象结果(基础结构体)
  274. struct OBJ_RESULT{
  275. unsigned int obj_id;//对象ID
  276. };
  277. //对象位置区域描述
  278. template<class T> struct OBJ_RECT{
  279. T centerx;
  280. T centery;
  281. T width;
  282. T height;
  283. double angle;
  284. };
  285. //定位点识别结果
  286. struct LOCATE_POINT_RESULT :OBJ_RESULT, OBJ_RECT<float>{
  287. };
  288. //二维码识别结果
  289. struct CODE_RESULT :OBJ_RESULT, OBJ_RECT<float>{
  290. std::string qr_str;
  291. bool is_stu_id;
  292. };
  293. struct CLIP_RESULT{
  294. //在原试卷的位置
  295. //图像数据地址
  296. unsigned char * img_data;
  297. //图像数据大小
  298. unsigned long img_data_size;
  299. //编号
  300. int index;
  301. //区域名称
  302. string area_name;
  303. };
  304. struct KGUANTI_OPTION_RESULT :OBJ_RECT<float>{
  305. float features[9];
  306. };
  307. //题目识别结果
  308. struct QUESTION_RESULT :OBJ_RESULT{
  309. string question_code;
  310. identify::OMR_QUESTION_TYPE omr_question_type;
  311. bool identifyed;
  312. int total; // 选做题总数
  313. int required; // 选做题需要选择几个
  314. int xuanze; // 当前题目是选择的第几个
  315. string question_code_all;// 选做题所有题号
  316. string question_code_temp;// 判断题组概念(question_code_all与question_code_temp不同时,是题组)
  317. double maxscore; //0没有小问
  318. QUESTION_RESULT(){
  319. total = 0; required = 0; xuanze = -1;
  320. }
  321. };
  322. //客观题识别结果
  323. struct KEGUANTI_RESULT :QUESTION_RESULT{
  324. OMR_QUESTION_STATE question_state;
  325. string answer;
  326. vector<KGUANTI_OPTION_RESULT> option;
  327. };
  328. //切割区域识别结果
  329. struct CUT_AREA_RESULT :OBJ_RESULT, OBJ_RECT<float>{
  330. std::string area_name;
  331. std::vector<unsigned char> img_data;
  332. int area_index;
  333. int area_sub_index;
  334. int is_cut; //0:原来false,1原来true,2特殊处理,不带f图片
  335. std::string area_name_by_questionNo;
  336. };
  337. //填空题识别结果
  338. struct TIANKONGTI_RESULT :QUESTION_RESULT, OBJ_RECT<float>{
  339. float question_score;
  340. bool isright;
  341. };
  342. //主观题识别结果
  343. struct ZHUGUANTI_RESULT :QUESTION_RESULT{
  344. float question_score;
  345. OMR_QUESTION_STATE question_state;
  346. vector<OBJ_RECT<float>> option;
  347. };
  348. class OMR_RESULT{
  349. public:
  350. //是否已经正确识别
  351. bool identified;
  352. //识别信息
  353. string identify_msg;
  354. //逻辑页号
  355. long logic_page_number;
  356. //物理页号
  357. long phy_card_number;
  358. //图像文件路径
  359. string img_path;
  360. //图像文件路径
  361. string img_oldpath;
  362. bool is_same_exam_id;
  363. bool is_front_page;
  364. bool is_use_qr_code;
  365. bool examid_by_qr_code; // 是否识别二维码
  366. //该页索引
  367. int card_index;
  368. //识别二维码情况(1识别成功,0:未进入,-1识别失败)
  369. int card_qrFlag;
  370. //页名称
  371. string card_name;
  372. //试卷ID 重新识别时使用
  373. int paper_id;
  374. std::string online_card_paperid;
  375. std::string strMagicClassId;
  376. std::string strMagicStudentId;
  377. int schoolCardStatus; // 使用学号状态
  378. // 缺考标记
  379. bool quekaoFlag;
  380. //处理时间,毫秒
  381. int time;
  382. /************************************************************************/
  383. /* 二维码结果 */
  384. /************************************************************************/
  385. vector<CODE_RESULT> qr_result;
  386. //定位点读取结果
  387. vector<LOCATE_POINT_RESULT> locatepoint_result;
  388. /************************************************************************/
  389. /*客观题结果 */
  390. /************************************************************************/
  391. vector<KEGUANTI_RESULT> group_result;
  392. /************************************************************************/
  393. /* 图像切割结果 */
  394. /************************************************************************/
  395. vector<CUT_AREA_RESULT> cut_area_result;
  396. //填空题读取结果
  397. vector<TIANKONGTI_RESULT> tiankongti_result;
  398. //主观题读取结果
  399. vector<ZHUGUANTI_RESULT> zhutuanti_result;
  400. public:
  401. #ifdef _DEBUG
  402. OMR_RESULT(){
  403. }
  404. #endif
  405. void reset(){
  406. online_card_paperid = "";
  407. quekaoFlag = false;
  408. identified = false;
  409. identify_msg = "";
  410. logic_page_number = -1;
  411. phy_card_number=-1;
  412. img_path=-1;
  413. card_index=-1;
  414. card_name=-1;
  415. paper_id=-1;
  416. time=-1;
  417. qr_result.clear();
  418. locatepoint_result.clear();
  419. group_result.clear();
  420. cut_area_result.clear();
  421. tiankongti_result.clear();
  422. zhutuanti_result.clear();
  423. is_same_exam_id=true;
  424. is_front_page=false;
  425. is_use_qr_code=false;
  426. }
  427. };
  428. }
  429. }