环境搭建参考:
Emgu CV4图像处理之环境搭建1(C#)_zxy2847225301的博客-CSDN博客
从图像文件中加载并检测参考:
Emgu CV3+C#图像处理(六):霍夫圆检测/线检测 & 矩形/三角形检测_阿卡蒂奥的博客-CSDN博客_霍夫矩形检测
测试环境:
win10 64位
vistual studio 2019 (.net framework控制台程序)
Emgu CV 4.6.0
添加的dll引用和环境搭建的一样
本文要实现的效果是从摄像头中采集图像,然后送进public static Mat ProcessImage(Mat img)方法进行图像处理
详细代码如下:
static void Main(string[] args)
{
ImageViewer viewer = new ImageViewer(); //create an image viewer
VideoCapture capture = new VideoCapture(); //create a camera captue
Application.Idle += new EventHandler(delegate (object sender, EventArgs e)
{ //run this until application closed (close button click on image viewer)
Mat mat=capture.QueryFrame();
if (mat != null)
{
viewer.Image = ProcessImage(mat); //绘制从摄像头采集到的图片到ImageViewer中显示 draw the image obtained from camera
}
});
viewer.ShowDialog(); //show the image viewer
}
public static Mat ProcessImage(Mat img)
{
using (UMat gray = new UMat())
using (UMat cannyEdges = new UMat())
using (Mat triangleRectangleImage = new Mat(img.Size, DepthType.Cv8U, 3)) //image to draw triangles and rectangles on 三角形和矩形
using (Mat circleImage = new Mat(img.Size, DepthType.Cv8U, 3)) //image to draw circles on 圆形
using (Mat lineImage = new Mat(img.Size, DepthType.Cv8U, 3)) //image to drtaw lines on 直线
{
//将图片转为灰度图和降噪Convert the image to grayscale and filter out the noise
CvInvoke.CvtColor(img, gray, ColorConversion.Bgr2Gray);
//去除噪声Remove noise
CvInvoke.GaussianBlur(gray, gray, new Size(3, 3), 1);
#region 圆形检测circle detection
double cannyThreshold = 180.0;
double circleAccumulatorThreshold = 120;
CircleF[] circles = CvInvoke.HoughCircles(gray, HoughModes.Gradient, 2.0, 20.0, cannyThreshold,
circleAccumulatorThreshold, 5);
#endregion
#region 边缘检测Canny and edge detection
double cannyThresholdLinking = 120.0;
CvInvoke.Canny(gray, cannyEdges, cannyThreshold, cannyThresholdLinking);
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
#region 绘制Triangles and Rectangles文本到triangleRectangleImage中 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));
//绘制Triangles and Rectangles文本 Draw the labels
CvInvoke.PutText(triangleRectangleImage, "Triangles and Rectangles", new Point(20, 20),
FontFace.HersheyDuplex, 0.5, new MCvScalar(120, 120, 120));
#endregion
#region 绘制Circles文本到circleImage图中 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 把Lines文本绘制到图lineImage中 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));
//绘制Lines文本 Draw the labels
CvInvoke.PutText(lineImage, "Lines", new Point(20, 20), FontFace.HersheyDuplex, 0.5,
new MCvScalar(120, 120, 120));
#endregion
Mat result = new Mat();
//将原图img、三角形和矩形triangleRectangleImage、圆形circleImage、直线lineImage整合到result图中
CvInvoke.VConcat(new Mat[] { img, triangleRectangleImage, circleImage, lineImage }, result);
return result;
}
}
实现效果如下图(鼠标滚轮缩小一点就能看到了):