Click here to Skip to main content
15,879,239 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.CV.UI;
using System.Diagnostics;

namespace ShapeDetection
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();

fileNameTextBox.Text = "pic3.png";
}

public void PerformShapeDetection()
{
if (fileNameTextBox.Text != String.Empty)
{
StringBuilder msgBuilder = new StringBuilder("Performance: ");

//Load the image from file and resize it for display
Image<bgr,> img =
new Image<bgr,>(fileNameTextBox.Text)
.Resize(400, 400, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR, true);

//Convert the image to grayscale and filter out the noise
Image<gray,> gray = img.Convert<gray,>().PyrDown().PyrUp();

#region circle detection
Stopwatch watch = Stopwatch.StartNew();
Gray cannyThreshold = new Gray(180);
Gray circleAccumulatorThreshold = new Gray(120);
CircleF[] circles = gray.HoughCircles(
cannyThreshold,
circleAccumulatorThreshold,
2.0, //Resolution of the accumulator used to detect centers of the circles
20.0, //min distance
5, //min radius
0 //max radius
)[0]; //Get the circles from the first channel
watch.Stop();
msgBuilder.Append(String.Format("Hough circles - {0} ms; ", watch.ElapsedMilliseconds));
#endregion

#region Canny and edge detection
watch.Reset(); watch.Start();
Gray cannyThresholdLinking = new Gray(120);
Image<gray,> 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
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<mcvbox2d> boxList = new List<mcvbox2d>(); //a box is a rotated rectangle
using (MemStorage storage = new MemStorage()) //allocate storage for contour approximation
for (
Contour<point> 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.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 [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());
}
}
}
watch.Stop();
msgBuilder.Append(String.Format("Triangles & Rectangles - {0} ms; ", watch.ElapsedMilliseconds));
#endregion

originalImageBox.Image = img;
this.Text = msgBuilder.ToString();

#region draw triangles and rectangles
Image<bgr,> 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,> 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,> lineImage = img.CopyBlank();
foreach (LineSegment2D line in lines)
lineImage.Draw(line, new Bgr(Color.Green), 2);
lineImageBox.Image = lineImage;
#endregion
}
}

private void textBox1_TextChanged(object sender, EventArgs e)
{
PerformShapeDetection();
}

private void loadImageButton_Click(object sender, EventArgs e)
{
DialogResult result = openFileDialog1.ShowDialog();
if (result == DialogResult.OK || result == DialogResult.Yes)
{
fileNameTextBox.Text = openFileDialog1.FileName;
}
}

private void panel1_Paint(object sender, PaintEventArgs e)
{

}
}
}
Posted
Comments
BillWoodruff 21-Nov-14 4:49am    
Why aren't you asking this question on the Emgu support forum ? Note that questions with a large amount of code that the poster has not bothered to format are likely to get ignored here.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900