public int getAnswerNumber(Mat align, Rect r) { Mat roi = new Mat(align, r); Mat roi_gray = new Mat(), roi_edges = new Mat(); Imgproc.cvtColor(roi, roi_gray, Imgproc.COLOR_RGB2GRAY); Imgproc.Canny(roi_gray, roi_edges, 200, 200); // Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(2 + 1, 2 + 1), new Point(1, 1)); // Imgproc.dilate(roi_edges, roi_edges, element); //Shape detection List <MatOfPoint> contours = new List <MatOfPoint>(); Mat hierarchy = new Mat(); Imgproc.findContours(roi_edges, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE, new Point(0, 0)); List <MatOfPoint> hulls = new List <MatOfPoint>(); for (int i = 0; i < contours.Count; i++) { MatOfInt hull_temp = new MatOfInt(); Imgproc.convexHull(contours[i], hull_temp); int[] arrIndex = hull_temp.toArray(); Point[] arrContour = contours[i].toArray(); Point[] arrPoints = new Point[arrIndex.Length]; for (int k = 0; k < arrIndex.Length; k++) { arrPoints[k] = arrContour[arrIndex[k]]; } MatOfPoint temp = new MatOfPoint(); temp.fromArray(arrPoints); //Filter outliers if (Imgproc.contourArea(temp) > 40 && Imgproc.contourArea(temp) < 200) { hulls.Add(temp); } } List <MatOfPoint2f> hull2f = new List <MatOfPoint2f>(); for (int i = 0; i < hulls.Count; i++) { MatOfPoint2f newPoint = new MatOfPoint2f(hulls[i].toArray()); hull2f.Add(newPoint); } for (int i = 0; i < hulls.Count; i++) { //Approximate polygon MatOfPoint2f approx = new MatOfPoint2f(); Imgproc.approxPolyDP(hull2f[i], approx, 0.01 * Imgproc.arcLength(hull2f[i], true), true); List <Point> approx_polygon = approx.toList(); approx_polygon = Scannerproc.filterPolygon(approx_polygon); double area = Imgproc.contourArea(approx); //Center of mass int cx = 0, cy = 0; for (int k = 0; k < approx_polygon.Count; k++) { cx += (int)approx_polygon[k].x; cy += (int)approx_polygon[k].y; } cx /= approx_polygon.Count; cy /= approx_polygon.Count; // Imgproc.circle(roi, new Point(cx, cy), 5, new Scalar(255), -1); // Texture2D tex = new Texture2D(roi.width(), roi.height(), TextureFormat.RGB24, false); // Utils.matToTexture2D(roi, tex); // byte[] bytes1 = tex.EncodeToJPG(); // File.WriteAllBytes("D:/2019/OMR/" + "test.png", bytes1); Point pos1 = new Point((roi.width() * 1) / 10, cy); Point pos2 = new Point((roi.width() * 3) / 10, cy); Point pos3 = new Point((roi.width() * 5) / 10, cy); Point pos4 = new Point((roi.width() * 7) / 10, cy); Point pos5 = new Point((roi.width() * 9) / 10, cy); Point nowPos = new Point(cx, cy); double[] dist = new double[5]; dist[0] = Scannerproc.distanceTwoPoints(pos1, nowPos); dist[1] = Scannerproc.distanceTwoPoints(pos2, nowPos); dist[2] = Scannerproc.distanceTwoPoints(pos3, nowPos); dist[3] = Scannerproc.distanceTwoPoints(pos4, nowPos); dist[4] = Scannerproc.distanceTwoPoints(pos5, nowPos); int id = -1; double min_dist = 999999; for (int t = 0; t < 5; t++) { if (dist[t] < min_dist) { min_dist = dist[t]; id = t; } } return(id + 1); //return plusPoints(tl, new Point(cx, cy)); } return(0); }
public void getAnswerNumber(Mat align) { Mat align_gray = new Mat(), align_edges = new Mat(); Imgproc.cvtColor(align, align_gray, Imgproc.COLOR_RGB2GRAY); Imgproc.Canny(align_gray, align_edges, 50, 50); Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(2 + 1, 2 + 1), new Point(1, 1)); Imgproc.dilate(align_edges, align_edges, element); //Shape detection List <MatOfPoint> contours = new List <MatOfPoint>(); Mat hierarchy = new Mat(); Imgproc.findContours(align_edges, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE, new Point(0, 0)); List <MatOfPoint> hulls = new List <MatOfPoint>(); //Texture2D tex = new Texture2D(align_edges.width(), align_edges.height(), TextureFormat.RGB24, false); //Utils.matToTexture2D(align_edges, tex); //byte[] bytes1 = tex.EncodeToJPG(); //File.WriteAllBytes("D:/2019/OMR/" + "test.png", bytes1); for (int i = 0; i < contours.Count; i++) { MatOfInt hull_temp = new MatOfInt(); Imgproc.convexHull(contours[i], hull_temp); int[] arrIndex = hull_temp.toArray(); Point[] arrContour = contours[i].toArray(); Point[] arrPoints = new Point[arrIndex.Length]; for (int k = 0; k < arrIndex.Length; k++) { arrPoints[k] = arrContour[arrIndex[k]]; } MatOfPoint temp = new MatOfPoint(); temp.fromArray(arrPoints); //Filter outliers if (Imgproc.contourArea(temp) > 90000 && Imgproc.contourArea(temp) < 110000) { hulls.Add(temp); } } List <MatOfPoint2f> hull2f = new List <MatOfPoint2f>(); for (int i = 0; i < hulls.Count; i++) { MatOfPoint2f newPoint = new MatOfPoint2f(hulls[i].toArray()); hull2f.Add(newPoint); } List <Rect> rects = new List <Rect>(); for (int i = 0; i < hulls.Count; i++) { //Approximate polygon MatOfPoint2f approx = new MatOfPoint2f(); Imgproc.approxPolyDP(hull2f[i], approx, 0.01 * Imgproc.arcLength(hull2f[i], true), true); List <Point> approx_polygon = approx.toList(); approx_polygon = Scannerproc.filterPolygon(approx_polygon); double area = Imgproc.contourArea(approx); if (Scannerproc.isSquare(approx_polygon)) { Rect r = Imgproc.boundingRect(new MatOfPoint(approx_polygon.ToArray())); bool isContain = false; for (int k = 0; k < rects.Count; k++) { if (Scannerproc.distanceTwoPoints(rects[k].tl(), r.tl()) < 100) { //if (rects[k].contains(r) || r.contains(rects[k])) isContain = true; } } if (!isContain) { rects.Add(r); // Imgproc.rectangle(align, r.tl(), r.br(), new Scalar(255, 0, 0, 255), 3); for (int j = 1; j < 21; j++) { Rect roi = new Rect((int)r.tl().x + (int)((r.width * 1.3) / 6), (int)r.tl().y + (r.height / 21) * j, (int)((r.width * 4.7) / 6), r.height / 21); int num = getAnswerNumber(align, roi); if (num != 0) { Imgproc.putText(align, " " + num, new Point(roi.x - 40, roi.y + 25), 1, 2, new Scalar(255, 0, 0, 255), 3, Core.LINE_AA, false); Imgproc.rectangle(align, roi.tl(), roi.br(), new Scalar(0, 255, 0, 255), 2); } } } } //Center of mass int cx = 0, cy = 0; for (int k = 0; k < approx_polygon.Count; k++) { cx += (int)approx_polygon[k].x; cy += (int)approx_polygon[k].y; } cx /= approx_polygon.Count; cy /= approx_polygon.Count; // Imgproc.circle(roi, new Point(cx, cy), 5, new Scalar(255), -1); } if (rects.Count == 4) { nowDetected = false; } }