File.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. namespace HTEXScan.Models
  5. {
  6. /**文件**/
  7. class File
  8. {
  9. /**数据**/
  10. protected Data data = null;
  11. /**学生id**/
  12. protected Sid sid = null;
  13. /**绑定数据**/
  14. public void Bind(Data data)
  15. {
  16. this.data = data;
  17. }
  18. /**读取**/
  19. public void Read()
  20. {
  21. //原图
  22. OpenCvSharp.Mat mat = new OpenCvSharp.Mat(this.data.Path);
  23. //轮廓
  24. OpenCvSharp.Point[] contour = this.GetExternalContours(mat, 60, 120, 10);
  25. //顶点
  26. OpenCvSharp.Point2f[] vertex = this.GetVertexPoints(contour);
  27. //透视变换顶点
  28. OpenCvSharp.Point2f[] wrapVertex = this.GetWarperspectivePoints(mat, vertex);
  29. //透视变换图
  30. OpenCvSharp.Mat wpMat = this.WarpPerspective(mat, vertex, wrapVertex);
  31. //检测表格
  32. this.sid = new Sid();
  33. this.CheckCells(wpMat);
  34. this.data.Sid = this.sid.Get();
  35. OpenCvSharp.Cv2.Rectangle(mat, OpenCvSharp.Cv2.BoundingRect(contour), OpenCvSharp.Scalar.Red, 5);
  36. for (int i = 0; i < vertex.Length; i++)
  37. OpenCvSharp.Cv2.Circle(mat, vertex[i].ToPoint(), 20, OpenCvSharp.Scalar.Blue, 20);
  38. this.Save(mat, wpMat);
  39. if (this.data.Show)
  40. {
  41. this.Show(mat);
  42. this.Show(wpMat);
  43. }
  44. mat.Release();
  45. wpMat.Release();
  46. }
  47. /**最大轮廓**/
  48. protected int GetMaxContour(OpenCvSharp.Point[][] contours)
  49. {
  50. int i = 0, index = 0;
  51. double area = 0, maxArea = 0;
  52. for (i = 0; i < contours.Length; i++)
  53. {
  54. area = OpenCvSharp.Cv2.ContourArea(contours[i]);
  55. if (area > maxArea)
  56. {
  57. index = i;
  58. maxArea = area;
  59. }
  60. }
  61. return index;
  62. }
  63. /**获取外部最大轮廓**/
  64. protected OpenCvSharp.Point[] GetMaxExternalContours(OpenCvSharp.Mat grayMat, double thresh)
  65. {
  66. OpenCvSharp.Point[][] contours = null;
  67. OpenCvSharp.HierarchyIndex[] hierarchly = null;
  68. //二值化
  69. OpenCvSharp.Mat tsMat = new OpenCvSharp.Mat();
  70. OpenCvSharp.Cv2.Threshold(grayMat, tsMat, thresh, 255, OpenCvSharp.ThresholdTypes.Tozero);
  71. //高斯模糊
  72. OpenCvSharp.Mat blurredMat = new OpenCvSharp.Mat();
  73. OpenCvSharp.Cv2.GaussianBlur(tsMat, blurredMat, new OpenCvSharp.Size(5, 5), 0);
  74. //边缘检测
  75. OpenCvSharp.Mat edgedMat = new OpenCvSharp.Mat();
  76. OpenCvSharp.Cv2.Canny(blurredMat, edgedMat, 0, 255);
  77. OpenCvSharp.Cv2.FindContours(edgedMat, out contours, out hierarchly, OpenCvSharp.RetrievalModes.External, OpenCvSharp.ContourApproximationModes.ApproxSimple);
  78. tsMat.Release();
  79. blurredMat.Release();
  80. edgedMat.Release();
  81. return contours[this.GetMaxContour(contours)];
  82. }
  83. /**获取外部轮廓**/
  84. protected OpenCvSharp.Point[] GetExternalContours(OpenCvSharp.Mat mat, double threshStart, double threshEnd, double threshSep)
  85. {
  86. OpenCvSharp.Point[] contour = null, contourTmp;
  87. //灰度
  88. OpenCvSharp.Mat grayMat = new OpenCvSharp.Mat();
  89. OpenCvSharp.Cv2.CvtColor(mat, grayMat, OpenCvSharp.ColorConversionCodes.BGR2GRAY);
  90. for (double thresh = threshStart; thresh < threshEnd; thresh += threshSep)
  91. {
  92. contourTmp = this.GetMaxExternalContours(grayMat, thresh);
  93. if (contour == null || OpenCvSharp.Cv2.ContourArea(contourTmp) > OpenCvSharp.Cv2.ContourArea(contour))
  94. contour = contourTmp;
  95. }
  96. grayMat.Release();
  97. return contour;
  98. }
  99. /**轮廓顶点**/
  100. protected OpenCvSharp.Point2f[] GetVertexPoints(OpenCvSharp.Point[] contours)
  101. {
  102. OpenCvSharp.Point2f[] points = new OpenCvSharp.Point2f[4];
  103. double d0 = 0, d1 = 0, d2 = 0, d3 = 0, d = 0;
  104. OpenCvSharp.Rect rect = OpenCvSharp.Cv2.BoundingRect(contours);
  105. for (int i = 0; i < contours.Length; i++)
  106. {
  107. //矩形左上角
  108. d = System.Math.Sqrt( System.Math.Pow(contours[i].X - rect.X, 2) + System.Math.Pow(contours[i].Y - rect.Y, 2));
  109. if (d0 == 0 || d < d0)
  110. {
  111. d0 = d;
  112. points[0] = contours[i];
  113. }
  114. //矩形右上角
  115. d = System.Math.Sqrt( System.Math.Pow(contours[i].X - rect.X - rect.Width, 2) + System.Math.Pow(contours[i].Y - rect.Y, 2));
  116. if (d1 == 0 || d < d1)
  117. {
  118. d1 = d;
  119. points[1] = contours[i];
  120. }
  121. //矩形左下角
  122. d = System.Math.Sqrt( System.Math.Pow(contours[i].X - rect.X, 2) + System.Math.Pow(contours[i].Y - rect.Y - rect.Height, 2));
  123. if (d2 == 0 || d < d2)
  124. {
  125. d2 = d;
  126. points[2] = contours[i];
  127. }
  128. //矩形右下角
  129. d = System.Math.Sqrt( System.Math.Pow(contours[i].X - rect.X - rect.Width, 2) + System.Math.Pow(contours[i].Y - rect.Y - rect.Height, 2));
  130. if (d3 == 0 || d < d3)
  131. {
  132. d3 = d;
  133. points[3] = contours[i];
  134. }
  135. }
  136. return points;
  137. }
  138. /**获取透视变换点**/
  139. protected OpenCvSharp.Point2f[] GetWarperspectivePoints(OpenCvSharp.Mat mat, OpenCvSharp.Point2f[] points)
  140. {
  141. int cx = mat.Cols / 2, cy = mat.Rows / 2;
  142. OpenCvSharp.Point2f[] dstPoints = new OpenCvSharp.Point2f[4];
  143. for (int i = 0; i < points.Length; i++)
  144. {
  145. if (points[i].X <= cx && points[i].Y <= cy)
  146. dstPoints[i] = new OpenCvSharp.Point2f(0, 0);
  147. else if (points[i].X <= cx && points[i].Y > cy)
  148. dstPoints[i] = new OpenCvSharp.Point2f(0, mat.Rows);
  149. else if (points[i].X > cx && points[i].Y < cy)
  150. dstPoints[i] = new OpenCvSharp.Point2f(mat.Cols, 0);
  151. else
  152. dstPoints[i] = new OpenCvSharp.Point2f(mat.Cols, mat.Rows);
  153. }
  154. return dstPoints;
  155. }
  156. /**透视变换**/
  157. protected OpenCvSharp.Mat WarpPerspective(OpenCvSharp.Mat mat, OpenCvSharp.Point2f[] points, OpenCvSharp.Point2f[] toPoints)
  158. {
  159. OpenCvSharp.Mat wpMat = new OpenCvSharp.Mat();
  160. //获取透视变化矩阵
  161. OpenCvSharp.Mat mm = OpenCvSharp.Cv2.GetPerspectiveTransform(points, toPoints);
  162. OpenCvSharp.Cv2.WarpPerspective(mat, wpMat, mm, mat.Size());
  163. mm.Release();
  164. return wpMat;
  165. }
  166. /**检测表格**/
  167. protected void CheckCell(OpenCvSharp.Mat wpMat, OpenCvSharp.Mat mat, TemplateCell cell, OpenCvSharp.Rect matRect)
  168. {
  169. OpenCvSharp.Point[][] contours = null;
  170. OpenCvSharp.HierarchyIndex[] hierarchly = null;
  171. //二值化
  172. OpenCvSharp.Mat tsMat = new OpenCvSharp.Mat();
  173. OpenCvSharp.Cv2.Threshold(mat, tsMat, 0, 255, OpenCvSharp.ThresholdTypes.Binary | OpenCvSharp.ThresholdTypes.Triangle);
  174. //矩形
  175. OpenCvSharp.Cv2.Rectangle(tsMat, new OpenCvSharp.Rect(0, 0, mat.Width, mat.Height), OpenCvSharp.Scalar.White);
  176. //高斯模糊
  177. OpenCvSharp.Mat blurredMat = new OpenCvSharp.Mat();
  178. OpenCvSharp.Cv2.GaussianBlur(tsMat, blurredMat, new OpenCvSharp.Size(5, 5), 0);
  179. //边缘检测
  180. OpenCvSharp.Mat edgedMat = new OpenCvSharp.Mat();
  181. OpenCvSharp.Cv2.Canny(blurredMat, edgedMat, 0, 255);
  182. OpenCvSharp.Cv2.FindContours(edgedMat, out contours, out hierarchly, OpenCvSharp.RetrievalModes.List, OpenCvSharp.ContourApproximationModes.ApproxSimple);
  183. for (int i = 0; i < contours.Length; i++)
  184. {
  185. OpenCvSharp.Rect rect = OpenCvSharp.Cv2.BoundingRect(contours[i]);
  186. double s1 = rect.Width * rect.Height, s2 = mat.Width * mat.Height;
  187. if (s1 >= s2 * 0.35f && s1 <= s2 * 1.2f)
  188. {
  189. int cx = matRect.X + rect.X + rect.Width / 2, cy = matRect.Y + rect.Y + rect.Height / 2;
  190. if (matRect.Contains(cx, cy))
  191. {
  192. if (this.data.Show)
  193. {
  194. OpenCvSharp.Cv2.Circle(wpMat, new OpenCvSharp.Point(cx, cy), 5, OpenCvSharp.Scalar.Green, 2);
  195. OpenCvSharp.Cv2.Circle(wpMat, new OpenCvSharp.Point(matRect.X + matRect.Width / 2, matRect.Y + matRect.Height / 2), 15, OpenCvSharp.Scalar.Blue, 2);
  196. }
  197. if (cell.Type == 1)
  198. this.sid.Add(cell.Col, cell.Text);
  199. if(cell.Type == 2)
  200. {
  201. Subject subject =null;
  202. if (this.data.Subject == null)
  203. {
  204. this.data.Subject = new List<Subject>();
  205. subject = new Subject();
  206. subject.I = cell.Col;
  207. subject.Answer = new List<char>();
  208. this.data.Subject.Add(subject);
  209. }
  210. else
  211. {
  212. for(int m = 0;m < this.data.Subject.Count;m++)
  213. {
  214. if (this.data.Subject[m].I == cell.Col)
  215. {
  216. subject = this.data.Subject[m];
  217. break;
  218. }
  219. }
  220. if(subject == null)
  221. {
  222. subject = new Subject();
  223. subject.I = cell.Col;
  224. subject.Answer = new List<char>();
  225. this.data.Subject.Add(subject);
  226. }
  227. }
  228. subject.Answer.Add(cell.Text);
  229. }
  230. break;
  231. }
  232. }
  233. }
  234. tsMat.Release();
  235. blurredMat.Release();
  236. edgedMat.Release();
  237. }
  238. /**检测表格集合**/
  239. protected void CheckCells(OpenCvSharp.Mat mat)
  240. {
  241. //灰度
  242. OpenCvSharp.Mat grayMat = new OpenCvSharp.Mat();
  243. OpenCvSharp.Cv2.CvtColor(mat, grayMat, OpenCvSharp.ColorConversionCodes.BGR2GRAY);
  244. float sw = mat.Width * 1.0f / this.data.Template.Bw, sh = mat.Height * 1.0f / this.data.Template.Bh;
  245. OpenCvSharp.Mat rio = null;
  246. OpenCvSharp.Rect rect = new OpenCvSharp.Rect();
  247. for (int i = 0; i < this.data.Template.Cell.Count; i++)
  248. {
  249. rect.X = (int)(this.data.Template.Cell[i].X * sw);
  250. rect.Y = (int)(this.data.Template.Cell[i].Y * sh);
  251. rect.Width = (int)(this.data.Template.Cell[i].W * sw);
  252. rect.Height = (int)(this.data.Template.Cell[i].H * sw);
  253. rio = new OpenCvSharp.Mat(grayMat, rect);
  254. this.CheckCell(mat, rio, this.data.Template.Cell[i], rect);
  255. }
  256. grayMat.Release();
  257. }
  258. /**保存**/
  259. public void Save(OpenCvSharp.Mat mat, OpenCvSharp.Mat wpMat)
  260. {
  261. if(this.data.InfoPath != null)
  262. {
  263. OpenCvSharp.Cv2.ImWrite(this.data.InfoPath + "//0.jpg", mat);
  264. OpenCvSharp.Cv2.ImWrite(this.data.InfoPath + "//1.jpg", wpMat);
  265. }
  266. }
  267. protected void Show(OpenCvSharp.Mat mat)
  268. {
  269. OpenCvSharp.Size size = new OpenCvSharp.Size(mat.Size().Width * 0.5f, mat.Size().Height * 0.5f);
  270. OpenCvSharp.Mat displayMat = new OpenCvSharp.Mat(size, mat.Type());
  271. OpenCvSharp.Cv2.Resize(mat, displayMat, size);
  272. OpenCvSharp.Cv2.ImShow("1", displayMat);
  273. OpenCvSharp.Cv2.WaitKey();
  274. displayMat.Release();
  275. }
  276. }
  277. }