PageIdentify.h 17 KB

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