public static bool IsRectangle(Contour <Point> contour, double toleranceAngle = 10.0) { if (contour.Total != 4) { return(false); } // determine if all the angles in the contour are within [80, 100] degree var pts = contour.ToArray(); var edges = PointCollection.PolyLine(pts, true); var isRectangle = true; for (var i = 0; i < edges.Length; i++) { var edge = edges[(i + 1) % edges.Length]; var angle = Math.Abs(edge.GetExteriorAngleDegree(edges[i])); var absAngle = Math.Abs(90.0 - angle); if (absAngle > toleranceAngle) { isRectangle = false; break; } } return(isRectangle); }
private static RotatedRect?getCheckboxPatternFromContoursOfImage(VectorOfPoint approxContour) { if (approxContour.Size == 4) { bool isRectangle = true; Point[] pts = approxContour.ToArray(); LineSegment2D[] edges = PointCollection.PolyLine(pts, true); for (int j = 0; j < edges.Length; j++) { double angle = Math.Abs( edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j])); if (angle < 80 || angle > 100) { isRectangle = false; break; } } if (isRectangle) { return(CvInvoke.MinAreaRect(approxContour)); } } return(null); }
private IEnumerable <Rectangle> GetBoundariesForProcessedImage(Mat edges) { List <Rectangle> boxList = new List <Rectangle>(); using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint()) { CvInvoke.FindContours(edges, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple); int contourCount = contours.Size; for (int i = 0; i < contourCount; i++) { using (VectorOfPoint approxContour = new VectorOfPoint()) using (VectorOfPoint approx = contours[i]) { CvInvoke.ApproxPolyDP(approx, approxContour, CvInvoke.ArcLength(approx, true) * 0.035, true); Point[] pts = approxContour.ToArray(); LineSegment2D[] edgesList = PointCollection.PolyLine(pts, true); double contourArea = CvInvoke.ContourArea(approxContour, true); if (contourArea >= 500 && contourArea <= edges.Width * edges.Height / 5.0) { Rectangle contourRectangle = GetRectangleFromContour(approxContour, edgesList); if (contourRectangle != default(Rectangle)) { boxList.Add(contourRectangle); } } } } } return(boxList); }
private bool IsRectangle(VectorOfPoint contour) { if (contour.Size != 4) { return(false); } Point[] points = contour.ToArray(); int delta = 10; LineSegment2D[] edges = PointCollection.PolyLine(points, true); for (int i = 0; i < edges.Length; i++) { double angle = Math.Abs(edges[(i + 1) % edges.Length].GetExteriorAngleDegree(edges[i])); if (angle < 90 - delta || angle > 90 + delta) { return(false); } } return(true); }
public static List <Shapes.Rectangle> FindRectangles(VideoProcessing vp, Bitmap frame) { List <Shapes.Rectangle> rects = new List <Shapes.Rectangle>(); using (Image <Bgr, Byte> img = new Image <Bgr, byte>(frame)) { // double cannyThresholdLinking = 120.0; // double cannyThreshold = 180.0; //Convert the image to grayscale and filter out the noise Image <Gray, Byte> gray = img.Convert <Gray, Byte>().PyrDown().PyrUp(); //Image<Gray, Byte> cannyEdges = gray.Canny(cannyThreshold, cannyThresholdLinking); using (MemStorage storage = new MemStorage()) { //allocate storage for contour approximation Contour <System.Drawing.Point> contours = gray.FindContours(CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, RETR_TYPE.CV_RETR_LIST, storage); for (; contours != null; contours = contours.HNext) { Contour <System.Drawing.Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.05, storage); if (currentContour.Area > 250) //only consider contours with area greater than 250 { if (currentContour.Total == 4) //The contour has 4 vertices. { #region determine if all the angles in the contour are within [80, 100] degree bool isRectangle = true; System.Drawing.Point[] pts = currentContour.ToArray(); LineSegment2D[] edges = PointCollection.PolyLine(pts, true); for (int i = 0; i < edges.Length; i++) { double angle = Math.Abs(edges[(i + 1) % edges.Length].GetExteriorAngleDegree(edges[i])); if (angle < 80 || angle > 100) { isRectangle = false; break; } } #endregion if (isRectangle) { var box = currentContour.GetMinAreaRect(); Shapes.Rectangle r = new Shapes.Rectangle(box.center.X, box.center.Y, box.angle); r.Height = box.size.Height; r.Width = box.size.Width; rects.Add(r); } } } } } } //ensure we dont have massive rectangles rects = rects.Where(x => (x.Height < .8 * vp.FrameSize.Height && x.Width < .8 * vp.FrameSize.Width)).ToList(); SetVideoProcessing(rects, vp); return(rects); }
private void fnFindTriangleRect() { triangleRectImage = img.CopyBlank(); using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint()) { CvInvoke.FindContours(cannyEdges, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple); int count = contours.Size; for (int i = 0; i < count; i++) { using (VectorOfPoint contour = contours[i]) using (VectorOfPoint approxContour = new VectorOfPoint()) { CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.05, true); if (CvInvoke.ContourArea(approxContour, false) > 250) //only consider contour with area > 250 { if (approxContour.Size == 3) //The contour has 3 vertices, is a triangle { Point[] pts = approxContour.ToArray(); triangleList.Add(new Triangle2DF(pts[0], pts[1], pts[2])); } else if (approxContour.Size == 4) // The contour has 4 vertices { #region Determine if all the angles in the contours are within [80,100] degree bool isRectangle = true; Point[] pts = approxContour.ToArray(); LineSegment2D[] edges = PointCollection.PolyLine(pts, true); for (int j = 0; j < edges.Length; j++) { double dAngle = Math.Abs(edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j])); if (dAngle < 80 || dAngle > 100) { isRectangle = false; break; } } #endregion if (isRectangle) { boxList.Add(CvInvoke.MinAreaRect(approxContour)); } } } } } } foreach (Triangle2DF triangle in triangleList) { triangleRectImage.Draw(triangle, new Bgr(Color.DarkBlue), 2); } foreach (RotatedRect box in boxList) { triangleRectImage.Draw(box, new Bgr(Color.Red), 2); } ImgBox_Triangle_Rect.Image = triangleRectImage.Bitmap; }
//fonction pour dessiner les limits des obj et creer leur centroide List <RotatedRect> DrawRectangle(Image <Gray, byte> imageSeuil, String name) { List <RotatedRect> boxList = new List <RotatedRect>(); contours = new VectorOfVectorOfPoint(); Mat m = new Mat(); CvInvoke.FindContours(imageSeuil, contours, m, Emgu.CV.CvEnum.RetrType.External, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple); for (int i = 0; i < contours.Size; i++) { double perimeter = CvInvoke.ArcLength(contours[i], true); VectorOfPoint approx = new VectorOfPoint(); CvInvoke.ApproxPolyDP(contours[i], approx, 0.04 * perimeter, true); if (CvInvoke.ContourArea(approx, false) > 250) //only consider contours with area greater than 250 { if (approx.Size == 4) //The contour has 4 vertices, it is a rectangle { bool isRectangle = true; Point[] pts = approx.ToArray(); LineSegment2D[] edges = PointCollection.PolyLine(pts, true); for (int j = 0; j < edges.Length; j++) { double angle = Math.Abs( edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j])); if (angle < 80 || angle > 100) { isRectangle = false; break; } } if (isRectangle) { boxList.Add(CvInvoke.MinAreaRect(approx)); } } foreach (RotatedRect box in boxList) { CvInvoke.Polylines(imageMat, Array.ConvertAll(box.GetVertices(), Point.Round), true, new Bgr(System.Drawing.Color.Blue).MCvScalar, 2); var moments = CvInvoke.Moments(contours[i]); int x = (int)(moments.M10 / moments.M00); int y = (int)(moments.M01 / moments.M00); CvInvoke.PutText(imageMat, name, new Point(x, y), Emgu.CV.CvEnum.FontFace.HersheySimplex, 0.5, new MCvScalar(0, 0, 255), 2); } } } return(boxList); }
} // ShapeDetection() //// private static void FindTrianglesAndRectangles(UMat cannyEdges, List <Triangle2DF> triangleList, List <RotatedRect> boxList) { using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint()) { CvInvoke.FindContours(cannyEdges, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple); int count = contours.Size; for (int i = 0; i < count; i++) { using (VectorOfPoint contour = contours[i]) using (VectorOfPoint approxContour = new VectorOfPoint()) { CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.05, true); if (CvInvoke.ContourArea(approxContour, false) > 250) //only consider contours with area greater than 250 { if (approxContour.Size == 3) //The contour has 3 vertices, it is a triangle { Point[] pts = approxContour.ToArray(); triangleList.Add(new Triangle2DF( pts[0], pts[1], pts[2] )); } else if (approxContour.Size == 4) //The contour has 4 vertices. { #region determine if all the angles in the contour are within [80, 100] degree bool isRectangle = true; Point[] pts = approxContour.ToArray(); LineSegment2D[] edges = PointCollection.PolyLine(pts, true); for (int j = 0; j < edges.Length; j++) { double angle = Math.Abs( edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j])); if (angle < 80 || angle > 100) { isRectangle = false; break; } } #endregion if (isRectangle) { boxList.Add(CvInvoke.MinAreaRect(approxContour)); } } } } } } } // FindTrianglesAndRectangles() ///
/// <summary> /// Check if the four points forms a parallelogram /// </summary> /// <param name="pts">The four points that defines a polygon</param> /// <returns>True if the four points defines a parallelogram</returns> private static bool IsParallelogram(Point[] pts) { LineSegment2D[] edges = PointCollection.PolyLine(pts, true); double diff1 = Math.Abs(edges[0].Length - edges[2].Length); double diff2 = Math.Abs(edges[1].Length - edges[3].Length); if (diff1 / edges[0].Length <= 0.05 && diff1 / edges[2].Length <= 0.05 && diff2 / edges[1].Length <= 0.05 && diff2 / edges[3].Length <= 0.05) { return(true); } return(false); }
private static bool isRectangle(Point[] pts) { LineSegment2D[] edges = PointCollection.PolyLine(pts, true); for (int j = 0; j < edges.Length; j++) { double angle = Math.Abs(edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j])); if (angle < 80 || angle > 100) { return(false); } } return(true); }
private bool isRectangle(Point[] points, int delta) { LineSegment2D[] edges = PointCollection.PolyLine(points, true); for (int i = 0; i < edges.Length; i++) { double angle = Math.Abs(edges[(i + 1) % edges.Length].GetExteriorAngleDegree(edges[i])); if (angle < 90 - delta || angle > 90 + delta) { return(false); } } return(true); }
private bool isRectangle(Point[] points) { int delta = 10; // максимальное отклонение от прямого угла LineSegment2D[] edges = PointCollection.PolyLine(points, true); for (int i = 0; i < edges.Length; i++) // обход всех ребер контура { double angle = Math.Abs(edges[(i + 1) % edges.Length].GetExteriorAngleDegree(edges[i])); if (angle < 90 - delta || angle > 90 + delta) // если угол непрямой { return(false); } } return(true); }
private List <Tuple <Point[], double> > BoxDetection(IImage cannyEdges) { List <Tuple <Point[], double> > boxList = new List <Tuple <Point[], double> >(); using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint()) { CvInvoke.FindContours((IImage)((ICloneable)cannyEdges).Clone(), contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple); int count = contours.Size; for (int i = 0; i < count; i++) { using (VectorOfPoint contour = contours[i]) using (VectorOfPoint approxContour = new VectorOfPoint()) { CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.05, true); var area = CvInvoke.ContourArea(approxContour, false); if (area > 250) //only consider contours with area greater than 250 { if (approxContour.Size == 4) //The contour has 4 vertices. { #region determine if all the angles in the contour are within [80, 100] degree bool isRectangle = true; Point[] pts = approxContour.ToArray(); LineSegment2D[] edges = PointCollection.PolyLine(pts, true); for (int j = 0; j < edges.Length; j++) { double angle = Math.Abs( edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j])); if (angle < 40 || angle > 130) { isRectangle = false; break; } } #endregion if (isRectangle) { boxList.Add(new Tuple <Point[], double>(approxContour.ToArray(), area)); // CvInvoke.MinAreaRect(approxContour)); } } } } } } return(boxList); }
private void ContourImage(Mat frame, VectorOfPoint contour, Rectangle boundingBox, double area) { // contour collection for the contour image output frame using (VectorOfPoint approxContour = new VectorOfPoint()) { bool isRectangle = true; Point[] pts = approxContour.ToArray(); LineSegment2D[] edges = PointCollection.PolyLine(pts, true); CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.10, true); // get an array of points in the contour if (contour.Size > 20 && area < 5000) // filters size of shapes shown { // Drawing contour and box around it if (approxContour.Size == 3) //The contour has 3 vertices, it is a triangle { CvInvoke.Polylines(frame, contour, true, new Bgr(Color.Green).MCvScalar); // adds colors to shapes } else if (approxContour.Size == 4) //The contour has 4 vertices, it is a square { for (int j = 0; j < edges.Length; j++) { double angle = Math.Abs( edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j])); if (angle < 80 || angle > 100) // verifies square edge angles { isRectangle = false; } } if (isRectangle == true) { CvInvoke.Polylines(frame, contour, true, new Bgr(Color.Red).MCvScalar); // adds colors to shapes } } else { } // Write information next to marked object Point center = new Point(boundingBox.X + boundingBox.Width / 2, boundingBox.Y + boundingBox.Height / 2); // center of bounding box CvInvoke.Circle(frame, center, 2, new Bgr(Color.Orange).MCvScalar, 3); // orange dot in center of bounding box } } }
private List <RotatedRect> Contours(Mat img) { List <RotatedRect> boxList = new List <RotatedRect>(); using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint()) { using (VectorOfPoint approxContour = new VectorOfPoint()) { Mat output = new Mat(); CvInvoke.FindContours(img, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple); int count = contours.Size; for (int i = 0; i < count; i++) { CvInvoke.ApproxPolyDP(contours[i], approxContour, CvInvoke.ArcLength(contours[i], true) * 0.05, true); if (CvInvoke.ContourArea(approxContour, false) > 200) { if (approxContour.Size == 4) //The contour has 4 vertices. { #region determine if all the angles in the contour are within [80, 100] degree bool isRectangle = true; Point[] pts = approxContour.ToArray(); LineSegment2D[] edges = PointCollection.PolyLine(pts, true); for (int j = 0; j < edges.Length; j++) { double angle = Math.Abs( edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j])); if (angle < 70 || angle > 110) { isRectangle = false; break; } } #endregion if (isRectangle) { boxList.Add(CvInvoke.MinAreaRect(approxContour)); } } } } } } return(boxList); }
private void rbRectangle_CheckedChanged(object sender, EventArgs e) { if (!rbRChecked) { CvInvoke.cvCvtColor(ori, edit, COLOR_CONVERSION.CV_BGR2GRAY); CvInvoke.cvCanny(edit, edit, 150, 60, 3); result = ori.Clone(); List <MCvBox2D> box = new List <MCvBox2D>(); for (Contour <Point> con = edit.FindContours(); con != null; con = con.HNext) { Contour <Point> conPoint = con.ApproxPoly(con.Perimeter * 0.16); if (conPoint.Total == 4) { bool Rect = true; Point[] pts = conPoint.ToArray(); LineSegment2D[] line = PointCollection.PolyLine(pts, true); for (int i = 0; i < line.Length; i++) { double angle = Math.Abs(line[(i + 1) % line.Length].GetExteriorAngleDegree(line[i])); if (angle < 80 || angle > 100) { Rect = false; break; } } if (Rect) { box.Add(conPoint.GetMinAreaRect()); } foreach (MCvBox2D boxs in box) { result.Draw(boxs, new Bgr(Color.Blue), 5); } } } rbRChecked = true; rbLChecked = false; rbCChecked = false; pictureBox.Image = result.ToBitmap(); } }
void Shapedetection(Image <Gray, byte> img, int contour) { boxList.Clear(); triList.Clear(); for (Contour <Point> con = img.FindContours(); con != null; con = con.HNext) { Contour <Point> con2 = con.ApproxPoly(con.Perimeter * 0.16, storage); if (con.Area > 250) { //Triangle if (contour == 3) { if (con2.Total == 3) { Point[] pts = con2.ToArray(); triList.Add(new Triangle2DF(pts[0], pts[1], pts[2])); } } //Rectangle else if (contour == 4) { if (con2.Total == 4) { bool isRect = true; Point[] pts = con2.ToArray(); LineSegment2D[] edge = PointCollection.PolyLine(pts, true); for (int i = 0; i < edge.Length; i++) { double angle = Math.Abs(edge[(i + 1) % edge.Length].GetExteriorAngleDegree(edge[i])); if (angle < 80 || angle > 100) { isRect = false; break; } } if (isRect) { boxList.Add(con2.GetMinAreaRect()); } } } } } }
/// <summary> /// Determines whether the angles are close enough to 90 degrees /// </summary> /// <param name="contour"></param> /// <returns></returns> private bool IsRectangle(Contour <Point> contour) { Point[] pts = contour.ToArray(); LineSegment2D[] edges = PointCollection.PolyLine(pts, true); for (int i = 0; i < edges.Length; i++) { LineSegment2D currentEdge = edges[i]; LineSegment2D nextEdge = edges[(i + 1) % edges.Length]; double angle = Math.Abs(nextEdge.GetExteriorAngleDegree(currentEdge)); if (angle < 80 || angle > 100) { return(false); } } return(true); }
private bool isRectangle(Point[] points, int minAreaOfRect) { int delta = 10; VectorOfPoint arr = new VectorOfPoint(points); LineSegment2D[] edges = PointCollection.PolyLine(points, true); for (int i = 0; i < edges.Length; i++) { double andle = Math.Abs(edges[(i + 1) % edges.Length].GetExteriorAngleDegree(edges[i])); if (andle < 90 - delta || andle > 90 + delta || CvInvoke.ContourArea(arr, false) < minAreaOfRect) { return(false); } } return(true); }
private List <MCvBox2D> GetQuadrilaterals(Image <Gray, Byte> image) { //List to store rectangles List <MCvBox2D> rectList = new List <MCvBox2D>(); using (MemStorage storage1 = new MemStorage()) for (Contour <System.Drawing.Point> contours1 = image.FindContours(); contours1 != null; contours1 = contours1.HNext) { //Polygon Approximations Contour <System.Drawing.Point> contoursAP = contours1.ApproxPoly(contours1.Perimeter * 0.05, storage1); //Use area to wipe out the unnecessary result if (contours1.Area >= 200) { //Use vertices to determine the shape if (contoursAP.Total == 4) { //Rectangle bool isRectangle = true; System.Drawing.Point[] points = contoursAP.ToArray(); LineSegment2D[] edges = PointCollection.PolyLine(points, true); //degree within the range of [75, 105] will be detected for (int i = 0; i < edges.Length; i++) { double angle = Math.Abs(edges[(i + 1) % edges.Length].GetExteriorAngleDegree(edges[i])); if (angle < 75 || angle > 105) { isRectangle = false; break; } } if (isRectangle) { rectList.Add(contoursAP.GetMinAreaRect()); } } } } return(rectList); }
/// <summary> /// Determina si un contorno es un rectangulo verificando que tenga 4 vertices y sus angulos sean 90° /// </summary> /// <param name="MaxAngleDeviationDeg"> Máxima desviacion permitida respecto a 90° </param> /// <returns></returns> public static bool isRectangle(this VectorOfPoint contour, float MaxAngleDeviationDeg = 10) { bool result = false; if (contour.Size == 4) { result = true; Point[] pts = contour.ToArray(); LineSegment2D[] edges = PointCollection.PolyLine(pts, true); for (int j = 0; j < edges.Length; j++) { double angle = Math.Abs(edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j])); if (angle < 90 - MaxAngleDeviationDeg || angle > 90 + MaxAngleDeviationDeg) { result = false; break; } } pts = null; edges = null; } return(result); }
private void DetectTriangle() { VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint(); CvInvoke.FindContours(gray, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple); for (int i = 0; i < contours.Size; i++) { VectorOfPoint contour = contours[i]; VectorOfPoint contourApprox = new VectorOfPoint(); CvInvoke.ApproxPolyDP(contour, contourApprox, CvInvoke.ArcLength(contour, true) * 0.1, true); Point[] points = contourApprox.ToArray(); if (contourApprox.Size == 3) { LineSegment2D[] lines = PointCollection.PolyLine(points, true); for (int j = 0; j < lines.Length; j++) { edit.Draw(lines[j], new Bgr(Color.Red), 2); } } } }
/// <summary> /// Determine if all the angles in the contour are within min/max angle. /// </summary> /// <param name="contour"></param> /// <param name="minAngle"></param> /// <param name="maxAngle"></param> /// <param name="minDetectAngles"></param> /// <param name="points"></param> /// <returns></returns> private bool IsPlausibleRectangle(Seq <DPoint> contour, int minAngle, int maxAngle, int minDetectAngles, out List <DPoint> points) { points = new List <DPoint>(); if (contour.Total < 4) { return(false); //The contour has less than 3 vertices. } var pts = contour.ToArray(); var edges = PointCollection.PolyLine(pts, true); var rightAngle = 0; for (var i = 0; i < edges.Length; i++) { var edge1 = edges[i]; var edge2 = edges[(i + 1) % edges.Length]; var edgeRatio = (edge1.Length / edge2.Length); points.Add(edge1.P1); var angle = Math.Abs(edge1.GetExteriorAngleDegree(edge2)); // stop if an angle is not in min/max angle range, no need to continue // also stop if connected edges are more than double in ratio if ((angle < minAngle || angle > maxAngle) || (edgeRatio > 5.0 || 1 / edgeRatio > 5.0)) { continue; } rightAngle++; } return(rightAngle >= minDetectAngles); }
/// <summary> /// Megkeresi openCV segítségével a paraméterként kapott képen az összes lehetséges négyszöget. /// </summary> /// <param name="img">A kép, melyen négyszögeket keresünk.</param> /// <returns>Az összes detektált négyzetet adja vissza.</returns> private List <MCvBox2D> Boxes(Image <Bgr, Byte> img) { List <MCvBox2D> boxList = new List <MCvBox2D>(); Image <Gray, Byte> gray = img.Convert <Gray, Byte>(); Image <Gray, Byte> cannyEdges = img.Canny(100.0, 60.0); Contour <Point> contours; using (MemStorage storage = new MemStorage()) for (contours = cannyEdges.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST, storage); contours != null; contours = contours.HNext) { Contour <Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.05, storage); bool isRectangle = true; Point[] pts = currentContour.ToArray(); LineSegment2D[] edges = PointCollection.PolyLine(pts, true); for (int i = 0; i < edges.Length; i++) { double angle = Math.Abs( edges[(i + 1) % edges.Length].GetExteriorAngleDegree(edges[i])); if (angle < 80 || angle > 100) { isRectangle = false; break; } } if (isRectangle) { boxList.Add(currentContour.GetMinAreaRect()); } } return(boxList); }
private LineSegment2D[] GetRightAngleEdges(Contour <Point> contour) { var pts = contour.ToArray(); var edges = PointCollection.PolyLine(pts, true); var longestEdge = edges[0]; var index = 0; for (var i = 1; i < edges.Length; i++) { var edge = edges[i]; // Assumption is that the longest edge defines the width of the tracked device in the blob if (edge.Length > longestEdge.Length) { index = i; longestEdge = edges[i]; } } var nextEdgeToLongestEdge = edges[(index + 1) % edges.Length]; return(new[] { longestEdge, nextEdgeToLongestEdge }); }
public Result PerformShapeDetection(VisionProfile profile, Mat img) { using (var gray = new Image <Gray, byte>(img.Bitmap)) using (var blurredGray = new Mat()) using (var finalOutput = new Mat()) { //K Must always be odd. CvInvoke.GaussianBlur(gray, blurredGray, System.Drawing.Size.Empty, profile.GaussianSigmaX); //Convert the image to grayscale and filter out the noise //UMat uimage = new UMat(); //CvInvoke.CvtColor(img, uimage, ColorConversion.Bgr2Gray); //use image pyr to remove noise UMat pyrDown = new UMat(); CvInvoke.PyrDown(img, pyrDown); CvInvoke.PyrUp(pyrDown, img); //Image<Gray, Byte> gray = img.Convert<Gray, Byte>().PyrDown().PyrUp(); var circles = CvInvoke.HoughCircles(img, HoughType.Gradient, profile.HoughCirclesDP, profile.HoughCirclesMinDistance, profile.HoughCirclesParam1, profile.HoughCirclesParam2, profile.HoughCirclesMinRadius, profile.HoughCirclesMaxRadius); UMat cannyEdges = new UMat(); CvInvoke.Canny(img, cannyEdges, profile.CannyLowThreshold, profile.CannyHighThreshold, profile.CannyApetureSize, profile.CannyGradient); var lines = CvInvoke.HoughLinesP(cannyEdges, profile.HoughLinesRHO, profile.HoughLinesTheta, profile.HoughLinesThreshold, profile.HoughLinesMinLineLength, profile.HoughLinesMaxLineGap); List <Triangle2DF> triangleList = new List <Triangle2DF>(); List <RotatedRect> boxList = new List <RotatedRect>(); //a box is a rotated rectangle using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint()) { CvInvoke.FindContours(cannyEdges, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple); int count = contours.Size; for (int i = 0; i < count; i++) { using (VectorOfPoint contour = contours[i]) using (VectorOfPoint approxContour = new VectorOfPoint()) { CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.05, true); if (CvInvoke.ContourArea(approxContour, false) > 250) //only consider contours with area greater than 250 { if (approxContour.Size == 3) //The contour has 3 vertices, it is a triangle { var pts = approxContour.ToArray(); triangleList.Add(new Triangle2DF( pts[0], pts[1], pts[2] )); } else if (approxContour.Size == 4) //The contour has 4 vertices. { #region determine if all the angles in the contour are within [80, 100] degree bool isRectangle = true; var pts = approxContour.ToArray(); LineSegment2D[] edges = PointCollection.PolyLine(pts, true); for (int j = 0; j < edges.Length; j++) { double angle = Math.Abs( edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j])); if (angle < 80 || angle > 100) { isRectangle = false; break; } } #endregion if (isRectangle) { boxList.Add(CvInvoke.MinAreaRect(approxContour)); } } } } } } var results = new Result(); results.Triangles = triangleList; results.Rects = boxList; results.Circles = circles.ToList(); results.Lines = lines.ToList(); return(results); } }
/// <summary> /// hand detection function /// </summary> /// <param name="skin">a binary image that contains skin like objects</param> /// <returns>a list that contains detected hands</returns> private List <Contour <Point> > HandDetection(Image <Gray, byte> skin) { Point first_peak = new Point(), first_valley = new Point(), reference_peak = new Point(), refernce_valley = new Point(); double[,] v1 = new double[2, 1], v2 = new double[2, 1]; double angle; int direction, length, mod; bool tester_peak = false, tester_valley = false; using (MemStorage storage = new MemStorage()) { handCandiate.Clear(); for (Contour <Point> i = skin.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_EXTERNAL, storage); i != null; i = i.HNext) { area = i.BoundingRectangle.Height * i.BoundingRectangle.Width; if (area > 3000 && !(i.Convex)) { tester_peak = false; tester_valley = false; skin.ROI = i.BoundingRectangle; this.center_pt = FindCentroidByDistanceTrans(skin); this.center_pt.X += skin.ROI.X; this.center_pt.Y += skin.ROI.Y; skin.ROI = Rectangle.Empty; Contour <Point> tt = i.ApproxPoly(accuracy, storage); LineSegment2D[] edges = PointCollection.PolyLine(tt.ToArray(), true); length = edges.Length; for (int ij = 0; ij < length; ij++) { mod = (ij + 1) % length; v1[0, 0] = edges[ij].P2.X - edges[ij].P1.X; v1[1, 0] = edges[ij].P2.Y - edges[ij].P1.Y; v2[0, 0] = edges[mod].P1.X - edges[mod].P2.X; v2[1, 0] = edges[mod].P1.Y - edges[mod].P2.Y; // this equation is quoted from http://www.mathworks.com/matlabcentral/newsreader/view_thread/276582 // and it is working very good angle = Math.Atan2(Math.Abs(det(v1, v2)), dot(v1, v2)) * (180.0 / Math.PI); if (angle < 90) { direction = dir(edges[ij].P1, edges[ij].P2, edges[mod].P2); if (direction > 0) { if ( ((edges[ij].Length <max_length && edges[ij].Length> min_length) || (edges[mod].Length <max_length && edges[mod].Length> min_length)) ) { if (!tester_valley) { tester_valley = true; refernce_valley = edges[ij].P2; numberOfValleys++; } else if (FindDistance(edges[ij].P2, first_valley) < min_length && FindDistance(edges[ij].P2, first_valley) > (0.5 * min_length) // && FindDistance(edges[ij].P2,center_pts) > min_length // && FindDistance(edges[ij].P2, center_pts) < max_length ) { if (tester_peak) { if (FindDistance(edges[ij].P2, first_peak) > min_length && FindDistance(edges[ij].P2, first_peak) < max_length ) { numberOfValleys++; } } } else if (FindDistance(edges[ij].P2, refernce_valley) < min_length && FindDistance(edges[ij].P2, refernce_valley) > (0.5 * min_length) // && FindDistance(edges[ij].P2, center_pts) > min_length // && FindDistance(edges[ij].P2, center_pts) < max_length ) { numberOfValleys++; } first_valley = edges[ij].P2; } } else { if ( (edges[ij].Length <max_length && edges[ij].Length> min_length) || (edges[mod].Length <max_length && edges[mod].Length> min_length) ) { if (!tester_peak) { tester_peak = true; reference_peak = edges[ij].P2; numberOfPeaks++; } else if (FindDistance(edges[ij].P2, first_peak) > min_length && FindDistance(edges[ij].P2, first_peak) < max_length) { if (tester_valley) { if (FindDistance(edges[ij].P2, first_valley) > min_length && FindDistance(edges[ij].P2, first_valley) < max_length ) { numberOfPeaks++; } } } else if (FindDistance(edges[ij].P2, reference_peak) > min_length && FindDistance(edges[ij].P2, reference_peak) < max_length) { numberOfPeaks++; } first_peak = edges[ij].P2; } } } } if (numberOfPeaks >= 3 && numberOfValleys >= 3) { //double diff = CvInvoke.cvMatchShapes(i.Ptr, temp_contour.Ptr, CONTOURS_MATCH_TYPE.CV_CONTOUR_MATCH_I1, 0); // if (diff < 0.1) // { newImage.Draw(i.BoundingRectangle, color_blue, 2); imageBoxSkin.Image = newImage; if (!hand_centers.Any()) { hand_centers.Add(0, center_pt); } else { double dis = FindDistance(center_pt, hand_centers[0]); if (dis < 200) { continue; } else { hand_centers.Add(1, center_pt); } } Rectangle te = i.BoundingRectangle; int teHeight = (int)(max_length + min_length); if (te.Height > teHeight) { te.Height = teHeight; } if (te.Width > teHeight) { te.Width = teHeight; } skin.ROI = te; Contour <Point> hand_ = ExtractBiggestContour(skin); if (hand_ != null) { handCandiate.Add(hand_); } skin.ROI = Rectangle.Empty; // } } // } numberOfPeaks = 0; numberOfValleys = 0; } } } return(handCandiate); }
public string ProcessAndRender(IInputArray imageIn, IInputOutputArray imageOut) { Stopwatch watch = Stopwatch.StartNew(); #region Pre-processing //Convert the image to grayscale and filter out the noise CvInvoke.CvtColor(imageIn, _gray, ColorConversion.Bgr2Gray); //Remove noise CvInvoke.GaussianBlur(_gray, _gray, new Size(3, 3), 1); double cannyThreshold = 180.0; double cannyThresholdLinking = 120.0; CvInvoke.Canny(_gray, _cannyEdges, cannyThreshold, cannyThresholdLinking); #endregion #region circle detection double circleAccumulatorThreshold = 120; CircleF[] circles = CvInvoke.HoughCircles(_gray, HoughModes.Gradient, 2.0, 20.0, cannyThreshold, circleAccumulatorThreshold, 5); #endregion #region Edge detection LineSegment2D[] lines = CvInvoke.HoughLinesP( _cannyEdges, 1, //Distance resolution in pixel-related units Math.PI / 45.0, //Angle resolution measured in radians. 20, //threshold 30, //min Line width 10); //gap between lines #endregion #region Find triangles and rectangles List <Triangle2DF> triangleList = new List <Triangle2DF>(); List <RotatedRect> boxList = new List <RotatedRect>(); //a box is a rotated rectangle using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint()) { CvInvoke.FindContours(_cannyEdges, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple); int count = contours.Size; for (int i = 0; i < count; i++) { using (VectorOfPoint contour = contours[i]) using (VectorOfPoint approxContour = new VectorOfPoint()) { CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.05, true); if (CvInvoke.ContourArea(approxContour, false) > 250 ) //only consider contours with area greater than 250 { if (approxContour.Size == 3) //The contour has 3 vertices, it is a triangle { Point[] pts = approxContour.ToArray(); triangleList.Add(new Triangle2DF( pts[0], pts[1], pts[2] )); } else if (approxContour.Size == 4) //The contour has 4 vertices. { #region determine if all the angles in the contour are within [80, 100] degree bool isRectangle = true; Point[] pts = approxContour.ToArray(); LineSegment2D[] edges = PointCollection.PolyLine(pts, true); for (int j = 0; j < edges.Length; j++) { double angle = Math.Abs( edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j])); if (angle < 80 || angle > 100) { isRectangle = false; break; } } #endregion if (isRectangle) { boxList.Add(CvInvoke.MinAreaRect(approxContour)); } } } } } } #endregion watch.Stop(); using (Mat triangleRectangleImage = new Mat(_gray.Size, DepthType.Cv8U, 3)) //image to draw triangles and rectangles on using (Mat circleImage = new Mat(_gray.Size, DepthType.Cv8U, 3)) //image to draw circles on using (Mat lineImage = new Mat(_gray.Size, DepthType.Cv8U, 3)) //image to draw lines on { #region draw triangles and rectangles triangleRectangleImage.SetTo(new MCvScalar(0)); foreach (Triangle2DF triangle in triangleList) { CvInvoke.Polylines(triangleRectangleImage, Array.ConvertAll(triangle.GetVertices(), Point.Round), true, new Bgr(Color.DarkBlue).MCvScalar, 2); } foreach (RotatedRect box in boxList) { CvInvoke.Polylines(triangleRectangleImage, Array.ConvertAll(box.GetVertices(), Point.Round), true, new Bgr(Color.DarkOrange).MCvScalar, 2); } //Drawing a light gray frame around the image CvInvoke.Rectangle(triangleRectangleImage, new Rectangle(Point.Empty, new Size(triangleRectangleImage.Width - 1, triangleRectangleImage.Height - 1)), new MCvScalar(120, 120, 120)); //Draw the labels CvInvoke.PutText(triangleRectangleImage, "Triangles and Rectangles", new Point(20, 20), FontFace.HersheyDuplex, 0.5, new MCvScalar(120, 120, 120)); #endregion #region draw circles circleImage.SetTo(new MCvScalar(0)); foreach (CircleF circle in circles) { CvInvoke.Circle(circleImage, Point.Round(circle.Center), (int)circle.Radius, new Bgr(Color.Brown).MCvScalar, 2); } //Drawing a light gray frame around the image CvInvoke.Rectangle(circleImage, new Rectangle(Point.Empty, new Size(circleImage.Width - 1, circleImage.Height - 1)), new MCvScalar(120, 120, 120)); //Draw the labels CvInvoke.PutText(circleImage, "Circles", new Point(20, 20), FontFace.HersheyDuplex, 0.5, new MCvScalar(120, 120, 120)); #endregion #region draw lines lineImage.SetTo(new MCvScalar(0)); foreach (LineSegment2D line in lines) { CvInvoke.Line(lineImage, line.P1, line.P2, new Bgr(Color.Green).MCvScalar, 2); } //Drawing a light gray frame around the image CvInvoke.Rectangle(lineImage, new Rectangle(Point.Empty, new Size(lineImage.Width - 1, lineImage.Height - 1)), new MCvScalar(120, 120, 120)); //Draw the labels CvInvoke.PutText(lineImage, "Lines", new Point(20, 20), FontFace.HersheyDuplex, 0.5, new MCvScalar(120, 120, 120)); #endregion using (InputArray iaImageIn = imageIn.GetInputArray()) using (Mat imageInMat = iaImageIn.GetMat()) CvInvoke.VConcat(new Mat[] { imageInMat, triangleRectangleImage, circleImage, lineImage }, imageOut); } return(String.Format("Detected in {0} milliseconds.", watch.ElapsedMilliseconds)); }
//megkeresi a négyszögeket a képen. A felismert négyszögeket méretük alapján megpróbálja kategóriákba sorolni és csak azokat tekinti négyszögnek, amelyek a legtöbb elemszámú kategóriába esnek. Ezzel elkerülve, hogy pl a rajzlapot is felismerje négyszögként private Image <Bgr, Byte> GetRectangles(Image <Bgr, Byte> img, out List <MCvBox2D> boxlist) { Image <Gray, Byte> gray = img.Convert <Gray, Byte>(); Image <Gray, Byte> cannyEdges = img.Canny(100.0, 60.0); List <MCvBox2D> boxList = new List <MCvBox2D>(); Contour <Point> contours; using (MemStorage storage = new MemStorage()) for ( contours = cannyEdges.FindContours( Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST, storage); contours != null; contours = contours.HNext) { Contour <Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.05, storage); if (currentContour.Total == 4 && currentContour.Area > 50) { bool isRectangle = true; Point[] pts = currentContour.ToArray(); LineSegment2D[] edges = PointCollection.PolyLine(pts, true); for (int i = 0; i < edges.Length; i++) { double angle = Math.Abs( edges[(i + 1) % edges.Length].GetExteriorAngleDegree(edges[i])); if (angle < 80 || angle > 100) { isRectangle = false; break; } } if (isRectangle) { boxList.Add(currentContour.GetMinAreaRect()); } } } Image <Bgr, Byte> triangleRectangleImage = img.Copy(); bool tmp = false; int avg = 0; int max = 0; int[,] discVal = new int[20, 2]; foreach (MCvBox2D box in boxList) { int i = box.MinAreaRect().Width / 10; if (i < 20 && i > 3) { discVal[i, 0] += box.MinAreaRect().Width; discVal[i, 1]++; if (discVal[i, 1] > discVal[max, 1]) { max = i; } } } if (discVal[max, 1] != 0) { avg = discVal[max, 0] / discVal[max, 1]; } for (int i = 0; i < boxList.Count; i++) { if (boxList[i].MinAreaRect().Width > avg - 10 && boxList[i].MinAreaRect().Width < avg + 10) { triangleRectangleImage.Draw(boxList[i], new Bgr(0, 255, 0), 2); for (int j = i + 1; j < boxList.Count; j++) { double dist = Math.Sqrt((boxList[i].center.X - boxList[j].center.X) * (boxList[i].center.X - boxList[j].center.X) + (boxList[i].center.Y - boxList[j].center.Y) * (boxList[i].center.Y - boxList[j].center.Y)); if (dist < 10) { boxList.RemoveAt(j); } } } else { boxList.RemoveAt(i); i--; } } boxlist = boxList; return(triangleRectangleImage); //cannyEdges.Convert<Bgr, Byte>(); }
/// <summary> /// /// </summary> public void PerformShapeDetection() { { StringBuilder msgBuilder = new StringBuilder("Performance: "); int w = 1665, h = 2286; //Load the image from file and resize it for display Image <Bgr, Byte> img = new Image <Bgr, byte>(@"D:\paper\1456141019_地理_p1.tif").Resize(w, h, Emgu.CV.CvEnum.Inter.Linear, true); //图片转换为灰度 UMat uimage = new UMat(); CvInvoke.CvtColor(img, uimage, ColorConversion.Bgr2Gray); //去噪处理 UMat pyrDown = new UMat(); CvInvoke.PyrDown(uimage, pyrDown); CvInvoke.PyrUp(pyrDown, uimage); Stopwatch watch = Stopwatch.StartNew(); UMat cannyEdges = new UMat(); //Image<Gray, Byte> gray = img.Convert<Gray, Byte>().PyrDown().PyrUp(); double cannyThreshold = 360.0; #if false #region 1、识别圆形 double circleAccumulatorThreshold = 120; CircleF[] circles = CvInvoke.HoughCircles(uimage, HoughType.Gradient, 2.0, 20.0, cannyThreshold, circleAccumulatorThreshold, 5); watch.Stop(); msgBuilder.Append(String.Format("Hough circles - {0} ms; ", watch.ElapsedMilliseconds)); #endregion #endif #region Canny and edge detection watch.Reset(); watch.Start(); double cannyThresholdLinking = 120.0; CvInvoke.Canny(uimage, cannyEdges, cannyThreshold, cannyThresholdLinking); LineSegment2D[] lines = CvInvoke.HoughLinesP( cannyEdges, 1, //Distance resolution in pixel-related units Math.PI, //Angle resolution measured in radians. 20, //threshold 30, //min Line width 10); //gap between lines 间隔 watch.Stop(); msgBuilder.Append(String.Format("Canny & Hough lines - {0} ms; ", watch.ElapsedMilliseconds)); #endregion #region Find triangles and rectangles watch.Reset(); watch.Start(); List <Triangle2DF> triangleList = new List <Triangle2DF>(); List <RotatedRect> boxList = new List <RotatedRect>(); //a box is a rotated rectangle using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint()) { CvInvoke.FindContours(cannyEdges, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple); int count = contours.Size; for (int i = 0; i < count; i++) { using (VectorOfPoint contour = contours[i]) using (VectorOfPoint approxContour = new VectorOfPoint()) { CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.05, true); if (CvInvoke.ContourArea(approxContour, false) > 25) //only consider contours with area greater than 250 { //三角形 if (approxContour.Size == 3) //The contour has 3 vertices, it is a triangle { Point[] pts = approxContour.ToArray(); triangleList.Add(new Triangle2DF( pts[0], pts[1], pts[2])); } //四条边的矩形 else if (approxContour.Size == 4) //The contour has 4 vertices. { #region 确定轮廓所有的角度都在[ 80, 100 ]度之间 bool isRectangle = true; Point[] pts = approxContour.ToArray(); LineSegment2D[] edges = PointCollection.PolyLine(pts, true); for (int j = 0; j < edges.Length; j++) { double angle = Math.Abs(edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j]));//两个线条间的夹角 if (angle < 80 || angle > 100) { isRectangle = false; break; } } #endregion if (isRectangle) { boxList.Add(CvInvoke.MinAreaRect(approxContour)); } } } } } } watch.Stop(); msgBuilder.Append(String.Format("Triangles & Rectangles - {0} ms; ", watch.ElapsedMilliseconds)); #endregion 1、识别圆形 this.Text = msgBuilder.ToString(); img.Save("D:\\aaaa.tiff"); #region draw triangles and rectangles Mat triangleRectangleImage = new Mat(img.Size, DepthType.Cv8U, 3); triangleRectangleImage.SetTo(new MCvScalar(0));//三角形 //foreach (Triangle2DF triangle in triangleList) //{ // CvInvoke.Polylines(triangleRectangleImage, Array.ConvertAll(triangle.GetVertices(), Point.Round), true, new Bgr(Color.DarkBlue).MCvScalar, 2); //} foreach (RotatedRect box in boxList) { CvInvoke.Polylines(triangleRectangleImage, Array.ConvertAll(box.GetVertices(), Point.Round), true, new Bgr(Color.DarkOrange).MCvScalar, 2); } triangleRectangleImage.Save("D:\\ccc.tiff"); this.pictureBox1.Image = triangleRectangleImage.Bitmap; #endregion } }