{"id":180,"date":"2013-04-12T08:29:52","date_gmt":"2013-04-12T13:29:52","guid":{"rendered":"http:\/\/homepages.uc.edu\/~yaozo\/wordpress\/?p=180"},"modified":"2013-04-12T08:29:52","modified_gmt":"2013-04-12T13:29:52","slug":"shape-triangle-rectangle-circle-line-detection-in-csharp","status":"publish","type":"post","link":"https:\/\/zhuoyao.net\/index.php\/2013\/04\/12\/shape-triangle-rectangle-circle-line-detection-in-csharp\/","title":{"rendered":"Shape (Triangle, Rectangle, Circle, Line) Detection in CSharp"},"content":{"rendered":"<p><span style=\"color: green;\"><b>This project is part of the Emgu.CV.Example solution<\/b><\/span><\/p>\n<table id=\"toc\">\n<tbody>\n<tr>\n<td>\n<div id=\"toctitle\">\n<h2>Contents<\/h2>\n<p>[<a id=\"togglelink\" href=\"http:\/\/www.emgu.com\/wiki\/index.php\/Shape_(Triangle,_Rectangle,_Circle,_Line)_Detection_in_CSharp#\">hide<\/a>]<\/div>\n<ul>\n<li><a href=\"http:\/\/www.emgu.com\/wiki\/index.php\/Shape_(Triangle,_Rectangle,_Circle,_Line)_Detection_in_CSharp#System_Requirement\">1\u00a0System Requirement<\/a><\/li>\n<li><a href=\"http:\/\/www.emgu.com\/wiki\/index.php\/Shape_(Triangle,_Rectangle,_Circle,_Line)_Detection_in_CSharp#Shape_Detection\">2\u00a0Shape Detection<\/a><\/li>\n<li><a href=\"http:\/\/www.emgu.com\/wiki\/index.php\/Shape_(Triangle,_Rectangle,_Circle,_Line)_Detection_in_CSharp#Source_Code\">3\u00a0Source Code<\/a><\/li>\n<li><a href=\"http:\/\/www.emgu.com\/wiki\/index.php\/Shape_(Triangle,_Rectangle,_Circle,_Line)_Detection_in_CSharp#Result\">4\u00a0Result<\/a><\/li>\n<\/ul>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>System Requirement<\/h2>\n<table border=\"1px\" cellspacing=\"0\" cellpadding=\"10\">\n<tbody>\n<tr>\n<th>Component<\/th>\n<th>Requirement<\/th>\n<th>Detail<\/th>\n<\/tr>\n<tr>\n<td>Emgu CV<\/td>\n<td><a title=\"Version History\" href=\"http:\/\/www.emgu.com\/wiki\/index.php\/Version_History#Emgu.CV-1.5.0.0\">Version 1.5<\/a><\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td>Operation System<\/td>\n<td>Cross Platform<\/td>\n<td><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Shape Detection<\/h2>\n<p>In this tutorial, we demonstrate how to perform Hough Line and Circle detection using\u00a0<a title=\"Emgu CV\" href=\"http:\/\/www.emgu.com\/wiki\/index.php\/Emgu_CV\">Emgu CV<\/a>, as well as using the Contour class to detect Triangles and Rectangles in the image. The &#8220;pic3.png&#8221; file from the\u00a0<a title=\"OpenCV\" href=\"http:\/\/www.emgu.com\/wiki\/index.php\/OpenCV\">OpenCV<\/a>\u00a0sample folder is used here.<\/p>\n<div>\n<div>\n<div><a href=\"http:\/\/www.emgu.com\/wiki\/index.php\/File:Opencvpic3sample.png\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" src=\"http:\/\/www.emgu.com\/wiki\/images\/thumb\/Opencvpic3sample.png\/300px-Opencvpic3sample.png\" width=\"300\" height=\"225\" \/><\/a><\/p>\n<div>\n<div><a title=\"Enlarge\" href=\"http:\/\/www.emgu.com\/wiki\/index.php\/File:Opencvpic3sample.png\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" src=\"http:\/\/www.emgu.com\/wiki\/skins\/common\/images\/magnify-clip.png\" width=\"15\" height=\"11\" \/><\/a><\/div>\n<p>pic3.png from opencv<\/p><\/div>\n<\/div>\n<\/div>\n<\/div>\n<h2>Source Code<\/h2>\n<div dir=\"ltr\">\n<div>\n<pre>\/\/Load the image from file\nImage&lt;Bgr, Byte&gt; img = new Image&lt;Bgr, byte&gt;(fileNameTextBox.Text).Resize(400, 400, true);\n\n\/\/Convert the image to grayscale and filter out the noise\nImage&lt;Gray, Byte&gt; gray = img.Convert&lt;Gray, Byte&gt;().PyrDown().PyrUp();\n\nGray cannyThreshold = new Gray(180);\nGray cannyThresholdLinking = new Gray(120);\nGray circleAccumulatorThreshold = new Gray(120);\n\nCircleF[] circles = gray.HoughCircles(\n    cannyThreshold,\n    circleAccumulatorThreshold,\n    5.0, \/\/Resolution of the accumulator used to detect centers of the circles\n    10.0, \/\/min distance \n    5, \/\/min radius\n    0 \/\/max radius\n    )[0]; \/\/Get the circles from the first channel\n\nImage&lt;Gray, Byte&gt; cannyEdges = gray.Canny(cannyThreshold, cannyThresholdLinking);\nLineSegment2D[] lines = cannyEdges.HoughLinesBinary(\n    1, \/\/Distance resolution in pixel-related units\n    Math.PI \/ 45.0, \/\/Angle resolution measured in radians.\n    20, \/\/threshold\n    30, \/\/min Line width\n    10 \/\/gap between lines\n    )[0]; \/\/Get the lines from the first channel\n\n#region Find triangles and rectangles\nList&lt;Triangle2DF&gt; triangleList = new List&lt;Triangle2DF&gt;();\nList&lt;MCvBox2D&gt; boxList = new List&lt;MCvBox2D&gt;();\n\nusing (MemStorage storage = new MemStorage()) \/\/allocate storage for contour approximation\n   for (Contour&lt;Point&gt; contours = cannyEdges.FindContours(); contours != null; contours = contours.HNext)\n   {\n      Contour&lt;Point&gt; currentContour = contours.ApproxPoly(contours.Perimeter * 0.05, storage);\n\n      if (contours.Area &gt; 250) \/\/only consider contours with area greater than 250\n      {\n         if (currentContour.Total == 3) \/\/The contour has 3 vertices, it is a triangle\n         {\n            Point[] pts = currentContour.ToArray();\n            triangleList.Add(new Triangle2DF(\n               pts[0],\n               pts[1],\n               pts[2]\n               ));\n         }\n         else if (currentContour.Total == 4) \/\/The contour has 4 vertices.\n         {\n            #region determine if all the angles in the contour are within the range of [80, 100] degree\n            bool isRectangle = true;\n            Point[] pts = currentContour.ToArray();\n            LineSegment2D[] edges = PointCollection.PolyLine(pts, true);\n\n            for (int i = 0; i &lt; edges.Length; i++)\n            {\n               double angle = Math.Abs(\n                  edges[(i + 1) % edges.Length].GetExteriorAngleDegree(edges[i]));\n               if (angle &lt; 80 || angle &gt; 100)\n               {\n                  isRectangle = false;\n                  break;\n               }\n            }\n            #endregion\n\n            if (isRectangle) boxList.Add(currentContour.GetMinAreaRect());\n         }\n      }\n   }\n#endregion\n\noriginalImageBox.Image = img;\n\n#region draw triangles and rectangles\nImage&lt;Bgr, Byte&gt; triangleRectangleImage = img.CopyBlank();\nforeach (Triangle2DF triangle in triangleList)\n   triangleRectangleImage.Draw(triangle, new Bgr(Color.DarkBlue), 2);\nforeach (MCvBox2D box in boxList)\n   triangleRectangleImage.Draw(box, new Bgr(Color.DarkOrange), 2);\ntriangleRectangleImageBox.Image = triangleRectangleImage;\n#endregion\n\n#region draw circles\nImage&lt;Bgr, Byte&gt; circleImage = img.CopyBlank();\nforeach (CircleF circle in circles)\n   circleImage.Draw(circle, new Bgr(Color.Brown), 2);\ncircleImageBox.Image = circleImage;\n#endregion\n\n#region draw lines\nImage&lt;Bgr, Byte&gt; lineImage = img.CopyBlank();\nforeach (LineSegment2D line in lines)\n   lineImage.Draw(line, new Bgr(Color.Green), 2);\nlineImageBox.Image = lineImage;\n#endregion<\/pre>\n<\/div>\n<\/div>\n<h2>Result<\/h2>\n<div>\n<div>\n<div><a href=\"http:\/\/www.emgu.com\/wiki\/index.php\/File:ShapeDetectionExample.png\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" src=\"http:\/\/www.emgu.com\/wiki\/images\/thumb\/ShapeDetectionExample.png\/300px-ShapeDetectionExample.png\" width=\"300\" height=\"307\" \/><\/a><\/p>\n<div>\n<div><a title=\"Enlarge\" href=\"http:\/\/www.emgu.com\/wiki\/index.php\/File:ShapeDetectionExample.png\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" src=\"http:\/\/www.emgu.com\/wiki\/skins\/common\/images\/magnify-clip.png\" width=\"15\" height=\"11\" \/><\/a><\/div>\n<p>Result of shape detection<\/p><\/div>\n<div><\/div>\n<div><\/div>\n<div>http:\/\/www.emgu.com\/wiki\/index.php\/Shape_(Triangle,_Rectangle,_Circle,_Line)_Detection_in_CSharp<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>This project is part of the Emgu.CV.Example solution Contents [hide] 1\u00a0System Requirement 2\u00a0Shape Detection 3\u00a0Source Code 4\u00a0Result System Requirement Component Requirement Detail Emgu CV Version&hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[],"class_list":["post-180","post","type-post","status-publish","format-standard","hentry","category-image-processing"],"_links":{"self":[{"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/posts\/180","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/comments?post=180"}],"version-history":[{"count":0,"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/posts\/180\/revisions"}],"wp:attachment":[{"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/media?parent=180"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/categories?post=180"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/tags?post=180"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}