This project is part of the Emgu.CV.Example solution
Contents[hide] |
System Requirement
Component | Requirement | Detail |
---|---|---|
Emgu CV | Version 1.5 | |
Operation System | Cross Platform |
Shape Detection
In this tutorial, we demonstrate how to perform Hough Line and Circle detection using Emgu CV, as well as using the Contour class to detect Triangles and Rectangles in the image. The “pic3.png” file from the OpenCV sample folder is used here.
Source Code
//Load the image from file Image<Bgr, Byte> img = new Image<Bgr, byte>(fileNameTextBox.Text).Resize(400, 400, true); //Convert the image to grayscale and filter out the noise Image<Gray, Byte> gray = img.Convert<Gray, Byte>().PyrDown().PyrUp(); Gray cannyThreshold = new Gray(180); Gray cannyThresholdLinking = new Gray(120); Gray circleAccumulatorThreshold = new Gray(120); CircleF[] circles = gray.HoughCircles( cannyThreshold, circleAccumulatorThreshold, 5.0, //Resolution of the accumulator used to detect centers of the circles 10.0, //min distance 5, //min radius 0 //max radius )[0]; //Get the circles from the first channel Image<Gray, Byte> cannyEdges = gray.Canny(cannyThreshold, cannyThresholdLinking); LineSegment2D[] lines = cannyEdges.HoughLinesBinary( 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 )[0]; //Get the lines from the first channel #region Find triangles and rectangles List<Triangle2DF> triangleList = new List<Triangle2DF>(); List<MCvBox2D> boxList = new List<MCvBox2D>(); using (MemStorage storage = new MemStorage()) //allocate storage for contour approximation for (Contour<Point> contours = cannyEdges.FindContours(); contours != null; contours = contours.HNext) { Contour<Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.05, storage); if (contours.Area > 250) //only consider contours with area greater than 250 { if (currentContour.Total == 3) //The contour has 3 vertices, it is a triangle { Point[] pts = currentContour.ToArray(); triangleList.Add(new Triangle2DF( pts[0], pts[1], pts[2] )); } else if (currentContour.Total == 4) //The contour has 4 vertices. { #region determine if all the angles in the contour are within the range of [80, 100] degree 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; } } #endregion if (isRectangle) boxList.Add(currentContour.GetMinAreaRect()); } } } #endregion originalImageBox.Image = img; #region draw triangles and rectangles Image<Bgr, Byte> triangleRectangleImage = img.CopyBlank(); foreach (Triangle2DF triangle in triangleList) triangleRectangleImage.Draw(triangle, new Bgr(Color.DarkBlue), 2); foreach (MCvBox2D box in boxList) triangleRectangleImage.Draw(box, new Bgr(Color.DarkOrange), 2); triangleRectangleImageBox.Image = triangleRectangleImage; #endregion #region draw circles Image<Bgr, Byte> circleImage = img.CopyBlank(); foreach (CircleF circle in circles) circleImage.Draw(circle, new Bgr(Color.Brown), 2); circleImageBox.Image = circleImage; #endregion #region draw lines Image<Bgr, Byte> lineImage = img.CopyBlank(); foreach (LineSegment2D line in lines) lineImage.Draw(line, new Bgr(Color.Green), 2); lineImageBox.Image = lineImage; #endregion