123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace HTEXScan.Models
- {
- /**文件**/
- class File
- {
- /**数据**/
- protected Data data = null;
- /**学生id**/
- protected Sid sid = null;
- /**绑定数据**/
- public void Bind(Data data)
- {
- this.data = data;
- }
- /**读取**/
- public void Read()
- {
- //原图
- OpenCvSharp.Mat mat = new OpenCvSharp.Mat(this.data.Path);
- //轮廓
- OpenCvSharp.Point[] contour = this.GetExternalContours(mat, 60, 120, 10);
- //顶点
- OpenCvSharp.Point2f[] vertex = this.GetVertexPoints(contour);
- //透视变换顶点
- OpenCvSharp.Point2f[] wrapVertex = this.GetWarperspectivePoints(mat, vertex);
- //透视变换图
- OpenCvSharp.Mat wpMat = this.WarpPerspective(mat, vertex, wrapVertex);
- //检测表格
- this.sid = new Sid();
- this.CheckCells(wpMat);
- this.data.Sid = this.sid.Get();
- OpenCvSharp.Cv2.Rectangle(mat, OpenCvSharp.Cv2.BoundingRect(contour), OpenCvSharp.Scalar.Red, 5);
- for (int i = 0; i < vertex.Length; i++)
- OpenCvSharp.Cv2.Circle(mat, vertex[i].ToPoint(), 20, OpenCvSharp.Scalar.Blue, 20);
- this.Save(mat, wpMat);
- if (this.data.Show)
- {
- this.Show(mat);
- this.Show(wpMat);
- }
- mat.Release();
- wpMat.Release();
- }
- /**最大轮廓**/
- protected int GetMaxContour(OpenCvSharp.Point[][] contours)
- {
- int i = 0, index = 0;
- double area = 0, maxArea = 0;
- for (i = 0; i < contours.Length; i++)
- {
- area = OpenCvSharp.Cv2.ContourArea(contours[i]);
- if (area > maxArea)
- {
- index = i;
- maxArea = area;
- }
- }
- return index;
- }
- /**获取外部最大轮廓**/
- protected OpenCvSharp.Point[] GetMaxExternalContours(OpenCvSharp.Mat grayMat, double thresh)
- {
- OpenCvSharp.Point[][] contours = null;
- OpenCvSharp.HierarchyIndex[] hierarchly = null;
- //二值化
- OpenCvSharp.Mat tsMat = new OpenCvSharp.Mat();
- OpenCvSharp.Cv2.Threshold(grayMat, tsMat, thresh, 255, OpenCvSharp.ThresholdTypes.Tozero);
- //高斯模糊
- OpenCvSharp.Mat blurredMat = new OpenCvSharp.Mat();
- OpenCvSharp.Cv2.GaussianBlur(tsMat, blurredMat, new OpenCvSharp.Size(5, 5), 0);
- //边缘检测
- OpenCvSharp.Mat edgedMat = new OpenCvSharp.Mat();
- OpenCvSharp.Cv2.Canny(blurredMat, edgedMat, 0, 255);
- OpenCvSharp.Cv2.FindContours(edgedMat, out contours, out hierarchly, OpenCvSharp.RetrievalModes.External, OpenCvSharp.ContourApproximationModes.ApproxSimple);
- tsMat.Release();
- blurredMat.Release();
- edgedMat.Release();
- return contours[this.GetMaxContour(contours)];
- }
- /**获取外部轮廓**/
- protected OpenCvSharp.Point[] GetExternalContours(OpenCvSharp.Mat mat, double threshStart, double threshEnd, double threshSep)
- {
- OpenCvSharp.Point[] contour = null, contourTmp;
- //灰度
- OpenCvSharp.Mat grayMat = new OpenCvSharp.Mat();
- OpenCvSharp.Cv2.CvtColor(mat, grayMat, OpenCvSharp.ColorConversionCodes.BGR2GRAY);
- for (double thresh = threshStart; thresh < threshEnd; thresh += threshSep)
- {
- contourTmp = this.GetMaxExternalContours(grayMat, thresh);
- if (contour == null || OpenCvSharp.Cv2.ContourArea(contourTmp) > OpenCvSharp.Cv2.ContourArea(contour))
- contour = contourTmp;
- }
- grayMat.Release();
- return contour;
- }
- /**轮廓顶点**/
- protected OpenCvSharp.Point2f[] GetVertexPoints(OpenCvSharp.Point[] contours)
- {
- OpenCvSharp.Point2f[] points = new OpenCvSharp.Point2f[4];
- double d0 = 0, d1 = 0, d2 = 0, d3 = 0, d = 0;
- OpenCvSharp.Rect rect = OpenCvSharp.Cv2.BoundingRect(contours);
- for (int i = 0; i < contours.Length; i++)
- {
- //矩形左上角
- d = System.Math.Sqrt( System.Math.Pow(contours[i].X - rect.X, 2) + System.Math.Pow(contours[i].Y - rect.Y, 2));
- if (d0 == 0 || d < d0)
- {
- d0 = d;
- points[0] = contours[i];
- }
- //矩形右上角
- d = System.Math.Sqrt( System.Math.Pow(contours[i].X - rect.X - rect.Width, 2) + System.Math.Pow(contours[i].Y - rect.Y, 2));
- if (d1 == 0 || d < d1)
- {
- d1 = d;
- points[1] = contours[i];
- }
- //矩形左下角
- d = System.Math.Sqrt( System.Math.Pow(contours[i].X - rect.X, 2) + System.Math.Pow(contours[i].Y - rect.Y - rect.Height, 2));
- if (d2 == 0 || d < d2)
- {
- d2 = d;
- points[2] = contours[i];
- }
- //矩形右下角
- 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));
- if (d3 == 0 || d < d3)
- {
- d3 = d;
- points[3] = contours[i];
- }
- }
- return points;
- }
- /**获取透视变换点**/
- protected OpenCvSharp.Point2f[] GetWarperspectivePoints(OpenCvSharp.Mat mat, OpenCvSharp.Point2f[] points)
- {
- int cx = mat.Cols / 2, cy = mat.Rows / 2;
- OpenCvSharp.Point2f[] dstPoints = new OpenCvSharp.Point2f[4];
- for (int i = 0; i < points.Length; i++)
- {
- if (points[i].X <= cx && points[i].Y <= cy)
- dstPoints[i] = new OpenCvSharp.Point2f(0, 0);
- else if (points[i].X <= cx && points[i].Y > cy)
- dstPoints[i] = new OpenCvSharp.Point2f(0, mat.Rows);
- else if (points[i].X > cx && points[i].Y < cy)
- dstPoints[i] = new OpenCvSharp.Point2f(mat.Cols, 0);
- else
- dstPoints[i] = new OpenCvSharp.Point2f(mat.Cols, mat.Rows);
- }
- return dstPoints;
- }
- /**透视变换**/
- protected OpenCvSharp.Mat WarpPerspective(OpenCvSharp.Mat mat, OpenCvSharp.Point2f[] points, OpenCvSharp.Point2f[] toPoints)
- {
- OpenCvSharp.Mat wpMat = new OpenCvSharp.Mat();
- //获取透视变化矩阵
- OpenCvSharp.Mat mm = OpenCvSharp.Cv2.GetPerspectiveTransform(points, toPoints);
- OpenCvSharp.Cv2.WarpPerspective(mat, wpMat, mm, mat.Size());
- mm.Release();
- return wpMat;
- }
- /**检测表格**/
- protected void CheckCell(OpenCvSharp.Mat wpMat, OpenCvSharp.Mat mat, TemplateCell cell, OpenCvSharp.Rect matRect)
- {
- OpenCvSharp.Point[][] contours = null;
- OpenCvSharp.HierarchyIndex[] hierarchly = null;
- //二值化
- OpenCvSharp.Mat tsMat = new OpenCvSharp.Mat();
- OpenCvSharp.Cv2.Threshold(mat, tsMat, 0, 255, OpenCvSharp.ThresholdTypes.Binary | OpenCvSharp.ThresholdTypes.Triangle);
- //矩形
- OpenCvSharp.Cv2.Rectangle(tsMat, new OpenCvSharp.Rect(0, 0, mat.Width, mat.Height), OpenCvSharp.Scalar.White);
- //高斯模糊
- OpenCvSharp.Mat blurredMat = new OpenCvSharp.Mat();
- OpenCvSharp.Cv2.GaussianBlur(tsMat, blurredMat, new OpenCvSharp.Size(5, 5), 0);
- //边缘检测
- OpenCvSharp.Mat edgedMat = new OpenCvSharp.Mat();
- OpenCvSharp.Cv2.Canny(blurredMat, edgedMat, 0, 255);
- OpenCvSharp.Cv2.FindContours(edgedMat, out contours, out hierarchly, OpenCvSharp.RetrievalModes.List, OpenCvSharp.ContourApproximationModes.ApproxSimple);
- for (int i = 0; i < contours.Length; i++)
- {
- OpenCvSharp.Rect rect = OpenCvSharp.Cv2.BoundingRect(contours[i]);
- double s1 = rect.Width * rect.Height, s2 = mat.Width * mat.Height;
- if (s1 >= s2 * 0.35f && s1 <= s2 * 1.2f)
- {
- int cx = matRect.X + rect.X + rect.Width / 2, cy = matRect.Y + rect.Y + rect.Height / 2;
- if (matRect.Contains(cx, cy))
- {
- if (this.data.Show)
- {
- OpenCvSharp.Cv2.Circle(wpMat, new OpenCvSharp.Point(cx, cy), 5, OpenCvSharp.Scalar.Green, 2);
- OpenCvSharp.Cv2.Circle(wpMat, new OpenCvSharp.Point(matRect.X + matRect.Width / 2, matRect.Y + matRect.Height / 2), 15, OpenCvSharp.Scalar.Blue, 2);
- }
- if (cell.Type == 1)
- this.sid.Add(cell.Col, cell.Text);
- if(cell.Type == 2)
- {
- Subject subject =null;
- if (this.data.Subject == null)
- {
- this.data.Subject = new List<Subject>();
- subject = new Subject();
- subject.I = cell.Col;
- subject.Answer = new List<char>();
- this.data.Subject.Add(subject);
- }
- else
- {
- for(int m = 0;m < this.data.Subject.Count;m++)
- {
- if (this.data.Subject[m].I == cell.Col)
- {
- subject = this.data.Subject[m];
- break;
- }
- }
- if(subject == null)
- {
- subject = new Subject();
- subject.I = cell.Col;
- subject.Answer = new List<char>();
- this.data.Subject.Add(subject);
- }
- }
- subject.Answer.Add(cell.Text);
- }
- break;
- }
- }
- }
- tsMat.Release();
- blurredMat.Release();
- edgedMat.Release();
- }
- /**检测表格集合**/
- protected void CheckCells(OpenCvSharp.Mat mat)
- {
- //灰度
- OpenCvSharp.Mat grayMat = new OpenCvSharp.Mat();
- OpenCvSharp.Cv2.CvtColor(mat, grayMat, OpenCvSharp.ColorConversionCodes.BGR2GRAY);
- float sw = mat.Width * 1.0f / this.data.Template.Bw, sh = mat.Height * 1.0f / this.data.Template.Bh;
- OpenCvSharp.Mat rio = null;
- OpenCvSharp.Rect rect = new OpenCvSharp.Rect();
- for (int i = 0; i < this.data.Template.Cell.Count; i++)
- {
- rect.X = (int)(this.data.Template.Cell[i].X * sw);
- rect.Y = (int)(this.data.Template.Cell[i].Y * sh);
- rect.Width = (int)(this.data.Template.Cell[i].W * sw);
- rect.Height = (int)(this.data.Template.Cell[i].H * sw);
- rio = new OpenCvSharp.Mat(grayMat, rect);
- this.CheckCell(mat, rio, this.data.Template.Cell[i], rect);
- }
- grayMat.Release();
- }
- /**保存**/
- public void Save(OpenCvSharp.Mat mat, OpenCvSharp.Mat wpMat)
- {
- if(this.data.InfoPath != null)
- {
- OpenCvSharp.Cv2.ImWrite(this.data.InfoPath + "//0.jpg", mat);
- OpenCvSharp.Cv2.ImWrite(this.data.InfoPath + "//1.jpg", wpMat);
- }
- }
- protected void Show(OpenCvSharp.Mat mat)
- {
- OpenCvSharp.Size size = new OpenCvSharp.Size(mat.Size().Width * 0.5f, mat.Size().Height * 0.5f);
- OpenCvSharp.Mat displayMat = new OpenCvSharp.Mat(size, mat.Type());
- OpenCvSharp.Cv2.Resize(mat, displayMat, size);
- OpenCvSharp.Cv2.ImShow("1", displayMat);
- OpenCvSharp.Cv2.WaitKey();
- displayMat.Release();
- }
- }
- }
|