OnLineCardPageIdentifier.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. #pragma once
  2. #include "OnLineCardSchemaStruct.h"
  3. #include "schema_struct.h"
  4. #include "identify_struct.h"
  5. namespace OnLineCard{
  6. struct schema_const_param{
  7. //试卷宽度(扫描后图片的大小(可以使用像素),越大越准确)
  8. int shijuanwidth;
  9. //试卷高度
  10. int shijuanheight;
  11. //内容高度(考试文本最顶部内容到页码底部间距离)
  12. int contenth;
  13. //内容顶部缩进(第一个定位点上边框到考试文本内容最上边内容距离)
  14. int content_margin_top;
  15. //第一块最小高度(试卷最左上角的矩形框要求的最小高度)
  16. int first_content_min_height;
  17. //内容(左侧)检测x偏移量
  18. int content_detect_left_offsetx;
  19. //内容(右侧)检测x偏移量
  20. int content_detect_right_offsetx;
  21. //内容检测宽度
  22. int content_detect_w;
  23. /************************************************************************/
  24. /* 定位点相关常亮 */
  25. /************************************************************************/
  26. //上下左右4边定位点的最大最小宽高
  27. double main_locate_point;
  28. //主定位点在4个不同方向的最小宽度
  29. int minw[4];
  30. //主定位点在4个不同方向的最大宽度
  31. int maxw[4];
  32. //主定位点在4个不同方向的最小高度
  33. int minh[4];
  34. //主定位点在4个不同方向的最大高度
  35. int maxh[4];
  36. //版本定位点检测区域相对第一个定位点的位置 的x坐标
  37. int version_detect_offsetx;
  38. //版本定位点检测区域相对第一个定位点的位置 的y坐标
  39. int version_detect_offsety;
  40. //版本定位点检测区域宽度
  41. int version_detect_width;
  42. //版本定位点检测区域高度
  43. int version_detect_height;
  44. //版本定位点在4个不同方向的最小宽度
  45. int version_minw[4];
  46. //版本定位点在4个不同方向的最大宽度
  47. int version_maxw[4];
  48. //版本定位点在4个不同方向的最小高度
  49. int version_minh[4];
  50. //版本定位点在4个不同方向的最大高度
  51. int version_maxh[4];
  52. //题目定位点的最大宽高
  53. int left_offsetx;
  54. int right_offsetx;
  55. int qd_detect_w;
  56. int maxw2;
  57. int minw2;
  58. int maxh2;
  59. int minh2;
  60. /************************************************************************/
  61. /* 试卷条码位置相关常量 */
  62. /************************************************************************/
  63. //试卷条码位置(相对第一个定位点位置,大概位置不到真正的二维码区域,可以理解是放大扫描空间的图片区域)
  64. int paper_bar_offsetx;
  65. int paper_bar_offsety;
  66. int paper_bar_width;
  67. int paper_bar_height;
  68. /************************************************************************/
  69. /* 学生条码位置相关常量 */
  70. /************************************************************************/
  71. //试卷条码位置(相对第一个定位点位置,大概位置不到真正的二维码区域,可以理解是放大扫描空间的图片区域)
  72. int paper_bar_offsetx1;
  73. int paper_bar_offsety1;
  74. int paper_bar_width1;
  75. int paper_bar_height1;
  76. //缺考标记相关参数
  77. int quekao_item_offset_x;
  78. int quekao_item_offset_y;
  79. int quekao_item_width;
  80. int quekao_item_height;
  81. //学号
  82. #define stuid_max_question_count 14
  83. int stuid_max_question_count2;
  84. int stuid_question_offset[stuid_max_question_count];//每题x轴偏移量
  85. int stuid_tudian_w; //涂点宽度
  86. int stuid_tudian_h; //涂点高度
  87. int stuid_item_offset_y; //第一排涂点y轴偏移量
  88. int stuid_item_offset_len; //每排Y轴偏移量,因为是表格,所以间隔固定
  89. /************************************************************************/
  90. /* 客观题相关常量 */
  91. /************************************************************************/
  92. //每一横排最大选择题数量(存储空间)
  93. #define xuanze_max_question_count 24
  94. #define xuanze_max_item_count 4
  95. //每一横排最大选择题数量
  96. int xuanze_max_question_count2;
  97. int xuanze_question_offset[xuanze_max_question_count];//每题x轴偏移量
  98. int xuanze_item_offset[xuanze_max_item_count];//每题涂点y轴偏移量
  99. int xuanze_question_header_offsety;//题号的y坐标偏移
  100. int tudian_w;//涂点宽度
  101. int tudian_h;//涂点高度
  102. int xuanze_item_offset_y; //第一排涂点y轴偏移量
  103. int xuanze_item_offset_len; //每排Y轴偏移量,因为是表格,所以间隔固定
  104. /************************************************************************/
  105. /* 不定项选择相关常量(多选题) */
  106. /************************************************************************/
  107. //每一横排最大选择题数量(存储空间)
  108. #define xuanze_max_question_count3 24
  109. #define xuanze_max_item_count3 10
  110. //每一横排最大选择题数量
  111. int xuanze_max_question_count4;
  112. int xuanze_question_offset3[xuanze_max_question_count3];//每题x轴偏移量
  113. int xuanze_item_offset3[xuanze_max_item_count3];//每题涂点y轴偏移量
  114. int xuanze_question_header_offsety3;//题号的y坐标偏移
  115. int tudian_w3;//涂点宽度
  116. int tudian_h3;//涂点高度
  117. int xuanze_item_offset_y3; //第一排涂点y轴偏移量
  118. int xuanze_item_offset_len3; //每排Y轴偏移量,因为是表格,所以间隔固定
  119. /************************************************************************/
  120. /* 填空题相关常量 (江苏卷) */
  121. /************************************************************************/
  122. //评分框宽度
  123. int tikong_w;
  124. //评分框高度
  125. int tikong_h;
  126. //每一横排最大填空题数量
  127. #define tiangkong_max_question_count 2
  128. //每题x轴偏移量(相对题目定位点的偏移)
  129. int tiangkong_question_offset[tiangkong_max_question_count];
  130. //每题结束位置x轴偏移量
  131. int tiangkong_end_offset[tiangkong_max_question_count];
  132. //每题开始位置x轴偏移量
  133. int tiangkong_start_offset[tiangkong_max_question_count];
  134. //填空题评分框y偏移量
  135. int tiankong_offsety;
  136. //填空题切割区域y偏移量(相对题目定位点的偏移)
  137. int tiankong_area_offsety;
  138. //填空题切割区域高度
  139. int tiankong_area_height;
  140. //评分框宽度阀值(动态检查时用到)
  141. int tiankong_w2;
  142. //评分框宽度阀值误差范围
  143. int tiankong_w3;
  144. //评分框高度阀值
  145. int tiankong_h2;
  146. //评分框高度阀值误差范围
  147. int tiankong_h3;
  148. #define tiankong_per_mode_type 5
  149. //数组0:全国 1:江苏 2:浙江 3:大分数
  150. //评分框宽度
  151. int tikong_w_arr[tiankong_per_mode_type];
  152. //评分框高度
  153. int tikong_h_arr[tiankong_per_mode_type];
  154. //每题x轴偏移量(相对题目定位点的偏移),自定义一行一个填空题
  155. int tiangkong_question_offset_arr[tiankong_per_mode_type];
  156. //每题结束位置x轴偏移量
  157. int tiangkong_end_offset_arr[tiankong_per_mode_type];
  158. //每题开始位置x轴偏移量
  159. int tiangkong_start_offset_arr[tiankong_per_mode_type];
  160. //填空题评分框y偏移量
  161. int tiankong_offsety_arr[tiankong_per_mode_type];
  162. //填空题切割区域y偏移量(相对题目定位点的偏移)
  163. int tiankong_area_offsety_arr[tiankong_per_mode_type];
  164. //填空题切割区域高度
  165. int tiankong_area_height_arr[tiankong_per_mode_type];
  166. /************************************************************************/
  167. /* 填空题相关常量 (全国卷) 选择题和填空题共用一个题目定位点 */
  168. /************************************************************************/
  169. int qtikong_w;//评分框宽度
  170. int qtikong_h;//评分框高度
  171. //每一横排最大填空题数量
  172. #define qtiangkong_max_question_count 1
  173. #define qtiangkong_max_pai_count 4
  174. //每题x轴偏移量
  175. int qtiangkong_question_offset[tiangkong_max_question_count];
  176. //每题结束位置x轴偏移量
  177. int qtiangkong_end_offset[tiangkong_max_question_count];
  178. //每题开始位置x轴偏移量
  179. int qtiangkong_start_offset[tiangkong_max_question_count];
  180. //每题排y轴偏移量
  181. int qtiangkong_pai_offset[qtiangkong_max_pai_count];
  182. //填空题评分框y偏移量
  183. int qtiankong_offsety;
  184. //填空题切割区域y偏移量
  185. int qtiankong_area_offsety;
  186. //填空题切割区域高度
  187. int qtiankong_area_height;
  188. //评分框宽度阀值
  189. int qtiankong_w2;
  190. //评分框宽度阀值误差范围
  191. int qtiankong_w3;
  192. //评分框高度阀值
  193. int qtiankong_h2;
  194. //评分框高度阀值误差范围
  195. int qtiankong_h3;
  196. /************************************************************************/
  197. /* 主观题相关常量 */
  198. /************************************************************************/
  199. //每一横排评分框数量
  200. #define zhuguanti_max_question_count 23
  201. int zhuguanti_question_offset[zhuguanti_max_question_count];//每评分框x轴偏移量
  202. int zhuguanti_w;//评分框宽度
  203. int zhuguanti_h;//评分框高度
  204. int zhuguanti_h2;//评分框高度阀值(评分数据框上下两边距离)
  205. int zhuguanti_h3;//评分框高度阀值误差范围(允许的上下两边实际误差范围)
  206. //主观题偏移位置
  207. int zhuguanti_offsetx;
  208. int zhuguanti_offsety;
  209. int zhuguanti_item_count;//主观题总共格子数(目前23个)
  210. //主观题最后一个格子相对右边地位点的偏移量(右边第一个分数框到右边题目定位点距离)
  211. int zhuguanti_r_offsetx;
  212. int zhuguanti_r_offsety;
  213. //主管题格子的宽高
  214. int zhuguanti_item_w;
  215. int zhuguanti_item_h;
  216. double main_locate_point_distance;
  217. //题目定位点距离
  218. double question_locate_point_distance;
  219. int group_count;
  220. int group_question_count;
  221. /************************************************************************/
  222. /* 附加题相关常量 */
  223. /************************************************************************/
  224. #define qxuanzuoti_max_count 4
  225. int qxuanzuoti_question_offsetx[qxuanzuoti_max_count];
  226. int qxuanzuoti_question_offsety[qxuanzuoti_max_count];
  227. int qxuanzuoti_item_w;
  228. int qxuanzuoti_item_h;
  229. };
  230. //分析结果
  231. struct OnlineAnalyseResult{
  232. //填涂项数量
  233. int cellNum;
  234. //填涂项灰度平均值
  235. int cellAvgGray;
  236. //全局背景灰度
  237. int backGroundGray;
  238. //填涂项结果
  239. struct itemResult{
  240. //黑度
  241. double heidu;
  242. //模糊度
  243. double mohudu;
  244. //相对面积(黑点面积与总面积之比)
  245. double xiangdui_mianji;
  246. //相对值(有灰度与面积计算的一个参考值)
  247. double xiangdui_value;
  248. //填涂区域的平均灰度
  249. int avg_gray;
  250. //相对背景被涂黑点数
  251. int gray_num;
  252. //涂点大小
  253. int cell_size;
  254. //字符区域大小
  255. int char_area_size;
  256. //字符区域黑色点数(统计选项的字符区域的灰度判定为黑色的点数,用于统计试卷该选项全局的平均字符黑点数)
  257. int char_area_black_count;
  258. //字符区域黑色点的平均灰度
  259. double char_area_avg_gray;
  260. }itemAnalyseResult[2048];
  261. //平均黑度
  262. double avg_heidu;
  263. //浮动黑度
  264. double float_heidu;
  265. //黑度基准
  266. double benchmarkBlk;
  267. //所有点最大黑度的平均值
  268. double avgMax_heidu;
  269. //面积基准
  270. double benchmarkAreaBlk;
  271. //黑度阀值
  272. int heidu_fazhi;
  273. //字符区域黑点数的平均值
  274. double char_area_black_avg[16];
  275. };
  276. class COnLineCardPageIdentifier
  277. {
  278. public:
  279. COnLineCardPageIdentifier();
  280. ~COnLineCardPageIdentifier();
  281. //识别指定图像
  282. int Identify(const IplImage* img, void* out_result, int out_size);
  283. private:
  284. // 识别
  285. int Identify();
  286. //根据指定页面
  287. int Identify_impl();
  288. int BaseCheck();
  289. int ClipImg(SchemaPage& schemaPage, IplImage * dst);
  290. int ReadQuestionScore(SchemaPage &schemaPage, IplImage * dst, CvMemStorage* storage);
  291. int ReadKeGuanTi1(SchemaPage &schemaPage, IplImage * dst);
  292. int ReadStudentID(SchemaPage &schemaPage, IplImage * dst);
  293. bool ReadQuekaoFlag(SchemaPage &schemaPage, IplImage * dst);
  294. void InitalizeTempVar();
  295. //计算涂点属性
  296. inline int caculate_cell_property(SchemaPage& schemaPage, SchemaItem &item, IplImage * dst, int &cellSize, double &refArea, double &avg_gray, int &grayNum, double &mo_hu_du, double &gao_heidu,/*字符区域大小*/int &char_area_size,/*字符区域黑色点数(统计选项的字符区域的灰度判定为黑色的点数,用于统计试卷该选项全局的平均字符黑点数)*/int& char_area_black_count,/*字符区域黑色点的平均灰度*/double& char_area_avg_gray, int flag = 0);
  297. //获取全局背景灰度,通过统计所有涂点周围像素(灰度不小于160)的灰度平均值获得
  298. int caculate_global_background(SchemaPage& schemaPage, IplImage * dst, bool flag = false);//flag 检查学号
  299. //分析全局属性
  300. int analyseOmrPanoramic(SchemaPage& schemaPage);
  301. //根据分析结果生成结果字符串
  302. int GenerateOmrStr(SchemaPage& schemaPage);
  303. int GetBlackArea(const IplImage * dst);
  304. int SaveLocateInfo(SchemaPage& schemaPage, std::vector<CvPoint2D32f> &relationKey, std::vector<CvPoint2D32f> &relationValue);
  305. inline int GetRect(const int centerx, const int centery, const int width, const int height, RESULT_RECT& result_rect);
  306. public:
  307. template<class T> void SaveRect(CvRect& rect, T& result);
  308. template<class T> inline CvRect GetCVRect(T& code)
  309. {
  310. CvRect result_rect;
  311. result_rect.x = code.centerx - code.width / 2;
  312. result_rect.y = code.centery - code.height / 2;
  313. result_rect.width = code.width;
  314. result_rect.height = code.height;
  315. return result_rect;
  316. }
  317. template<class T > inline void DrawObjRect(IplImage * dst, T& obj_result, CvScalar& scalar);
  318. inline int GetRect2(const int centerx, const int centery, const int width, const int height, RESULT_RECT& result_rect);
  319. BOOL FindQuestionLocatePoint(IplImage * dst, SchemaLocatePoint& lp1, CvPoint2D32f& point1);
  320. double GetDistance(CvPoint2D32f point1, CvPoint2D32f point2);
  321. int FindQuestionLocatePoints(SchemaPage& schemaPage, IplImage * dst);
  322. template<typename T>inline int GetTransformPoint(CvMat& mat, T& srcx, T& srcy, T& dstx, T& dsty){
  323. dstx = (T)(CV_MAT_ELEM(mat, float, 0, 0)*srcx + CV_MAT_ELEM(mat, float, 0, 1)*srcy + CV_MAT_ELEM(mat, float, 0, 2));
  324. dsty = (T)(CV_MAT_ELEM(mat, float, 1, 0)*srcx + CV_MAT_ELEM(mat, float, 1, 1)*srcy + CV_MAT_ELEM(mat, float, 1, 2));
  325. return identify::result::IDF_SUCCESS;
  326. }
  327. int GetTianKongTiRedCount(IplImage * dst, const CvRect& rect_normal, const CvRect& rect_detect, int count, int multi);
  328. int GetZhuGuanTiRedCount(IplImage * dst, const CvRect& rect, const CvRect& normal_rect, int * red_counts, int * red_in_counts, int count, int multi,bool bTianKongTi=false);
  329. BOOL GetRedBinary(IplImage * dst, const CvRect& rect_detect, IplImage ** red_binary);
  330. int mycaculate_global_background(SchemaItem items[], int itemCount, IplImage * dst);
  331. int myanalyseOmrPanoramic(OnlineAnalyseResult& anlyseResultTemp, int count);
  332. int myGenerateOmrStr(OnlineAnalyseResult& anlyseResultTemp, int count);
  333. int ReadXuanZuoTi(SchemaPage& schemaPage, SchemaQuestionScore& qs, IplImage * dst);
  334. int GenerateOmrStr(SchemaPage& schemaPage, std::string &ret);
  335. void SetUseQr(std::string strQr, bool bUse);
  336. void SetOnlineScanType(int nOnlineScanType);
  337. void SetPaperMode(int mode);
  338. void SetIdentiforMode(int subject, int mode);
  339. void SetScanMode(int type);
  340. schema_const_param m_default_schema_param;
  341. int JiaoZheng_20200418(IplImage * src0, IplImage * &dst_img, const std::vector<CvRect> & top_locate_point_list, const std::vector<CvRect> & bottom_locate_point_list,
  342. const std::vector<CvRect> & word_location_point_list, int dir,
  343. double, double, int word_w, int word_h);
  344. int JiaoZheng_20200418_first(IplImage * src0, IplImage * &dst_img,
  345. const std::vector<CvRect> & top_locate_point_list, const std::vector<CvRect> & bottom_locate_point_list, const std::vector<CvRect> & word_location_point_list,
  346. int dir);
  347. int JiaoZheng_20200418_second_four(IplImage * src0_, IplImage * &dst_img,
  348. const std::vector<CvRect> & top_locate_point_list, const std::vector<CvRect> & bottom_locate_point_list, const std::vector<CvRect> & word_location_point_list,
  349. int dir);
  350. int JiaoZheng_20200418_second_five(IplImage * src0_, IplImage * &dst_img,
  351. const std::vector<CvRect> & top_locate_point_list, const std::vector<CvRect> & bottom_locate_point_list, const std::vector<CvRect> & word_location_point_list,
  352. int dir);
  353. int xuanzhuan(IplImage * src0, IplImage * &dst_img, CvRect myRect);
  354. void myscale_shema_param0(const schema_const_param& default_schema_const_param, schema_const_param& schema_param, double scale);
  355. void CalcPos(const Pos&pos, const CvPoint& offset, double w_scale, double h_scale, int &center_x, int &center_y, int &w, int &h);
  356. void InitScoreArea(SchemaQuestionScore&sqs, const ScoreBox&box, CvPoint offset, double w_scale, double h_scale);
  357. int createSchema(const IplImage* src, IplImage* *dst, SchemaPage* *pageSchema, const char * result_path, bool flag, std::string qr, bool bUseQr);
  358. OnLineCard::PaperTemplate* m_pTemplate;
  359. void SetTemplate(OnLineCard::PaperTemplate*pT);
  360. void SetPageDefault(SchemaPage& page);
  361. int OnLineCardJZ(IplImage* src, IplImage* &dst_img, int nPageIndex, int dir, std::vector<CvRect>&main_locate_point, int &wordloctlt);
  362. int MyFindDingWeiDian(IplImage * src_gray_img, CvMemStorage* storage, schema_const_param &schema_param, std::vector<CvRect>& locate_point_list, int & _dir);
  363. int MyFindBottomDingWeiDian(IplImage * src_gray_img, CvMemStorage* storage, schema_const_param &schema_param, std::vector<CvRect>& locate_point_list, int & _dir);
  364. int GetQrCode(IplImage* dst_gray_img, schema_const_param &schema_param, std::vector<CvRect> &main_locate_point, std::vector<SchemaCode> &codev, std::string& paper_id, std::string& student_code, int code_type);
  365. void DrawSchema(IplImage * dst_img, SchemaPage* & pageSchema);
  366. double CalcRectArea(IplImage* src, const std::vector<CvRect> & top_locate_point_list, const std::vector<CvRect> & bottom_locate_point_list);
  367. std::vector<CvRect> m_vecBottom;
  368. int obj_index;
  369. private:
  370. OnlineAnalyseResult anlyseResult;
  371. //源图像
  372. IplImage *src;
  373. //纸张进入时的旋转角度
  374. FeedDirection feedDirection;
  375. //模板
  376. std::vector<SchemaPage*> *schemaPages;
  377. std::vector<CvPoint2D32f> m_relationKey;
  378. std::vector<CvPoint2D32f> m_relationValue;
  379. int dianshu_meihaomi;
  380. bool m_bUseQr;
  381. int m_nOnlineScanType;
  382. std::string m_strQrClass;
  383. int m_scantype;
  384. int m_paper_mode;
  385. void* out_result;
  386. identify::result::OMR_RESULT* omr_result;
  387. int m_subjectMode;
  388. int m_identiforMode;
  389. private:
  390. //识别范围结果保存
  391. std::vector<CvRect> item_result;
  392. float data[6];
  393. std::vector<CvPoint2D32f> m_question_locate_points;
  394. std::vector<BOOL> m_question_locate_point_found;
  395. std::vector<SchemaItem> m_items;
  396. public:
  397. RTL_CRITICAL_SECTION* m_althom_rcs;
  398. public:
  399. int m_nXianXiaDaFenType;
  400. bool m_nBxuanxiang;
  401. };
  402. }