总结
1、轮廓可以绘制:正外接矩形、最小外接矩形、最小外接圆、最小椭圆:其中最小外接矩形与最小椭圆在绘制时,如果轮廓点少于5个,会导致异常;!!
2、轮廓多边形逼近函数ApproxPolyDp():输出结果为Point数组,可以使用CvInvoke.Polylines()函数进行绘制;
3、根据轮廓的面积,大小(按比例或绝对值)进行筛选,可以有效的提取出目标轮廓;
4、实验中第二个实例使用颜色识别提取轮廓更好。
epsilon : 单位为像素
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Emgu.CV;
using Emgu.Util;
using Emgu.CV.Structure;
using Emgu.CV.CvEnum;
using Emgu.CV.Util;
using System.Drawing;
namespace lesson26
{
class Program
{
static void Main(string[] args)
{
最小外接圆
//Mat src = CvInvoke.Imread("10.png");
//Mat dst = src.Clone();
//Mat grayImg = new Mat();
//CvInvoke.Imshow("input", src);
//CvInvoke.CvtColor(src, grayImg, ColorConversion.Bgr2Gray);
//CvInvoke.Threshold(grayImg, grayImg, 100, 255, ThresholdType.Binary);
//VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
//VectorOfRect hierarchy = new VectorOfRect();
//CvInvoke.FindContours(grayImg, contours, hierarchy, RetrType.External, ChainApproxMethod.ChainApproxNone);
//for(int i = 0; i < contours.Size; i++)
//{
// CircleF circleF = CvInvoke.MinEnclosingCircle(contours[i]); //计算最小外接圆
// RotatedRect rotatedRect = CvInvoke.FitEllipse(contours[i]); //计算外接椭圆
// Point rcenter = new Point((int)rotatedRect.Center.X, (int)rotatedRect.Center.Y);
// Point center = new Point((int)circleF.Center.X,(int)circleF.Center.Y);
// CvInvoke.Circle(dst, center, (int)circleF.Radius, new MCvScalar(255, 0, 0), 2);
// CvInvoke.Ellipse(dst, rcenter, new Size((int)(rotatedRect.Size.Width/2), (int)(rotatedRect.Size.Height/2)), rotatedRect.Angle, 0, 360,
// new MCvScalar(0, 0, 255), 2);
// ///求取面积、周长、多边形逼近
// double length = CvInvoke.ArcLength(contours[i], true); //计算轮廓周长
// double area = CvInvoke.ContourArea(contours[i], false); //计算轮廓面积
// Console.WriteLine("contour {0} area: {1:N2}", i, length);
// Console.WriteLine("contour {0} length: {1:N2}", i, area);
// VectorOfPoint approxPoly = new VectorOfPoint();
// CvInvoke.ApproxPolyDP(contours[i], approxPoly, length * 0.02 , true); //多变形轮廓拟合
// CvInvoke.Polylines(dst, approxPoly, true, new MCvScalar(255, 255, 0), 2); //绘制拟合多边形
//}
//CvInvoke.Imshow("result", dst);
//CvInvoke.WaitKey(0);
//利用掩膜不规则轮廓提取
Mat src = CvInvoke.Imread("220.jpg");
Mat dst = new Mat(src.Size, DepthType.Cv8U, 3);
dst.SetTo(new MCvScalar(0, 0, 0));
Mat maskImg = dst.Clone();
CvInvoke.Imshow("input", src);
Mat grayImg = new Mat();
CvInvoke.CvtColor(src, grayImg, ColorConversion.Bgr2Gray);
CvInvoke.Threshold(grayImg, grayImg, 100, 255, ThresholdType.BinaryInv);
CvInvoke.Imshow("threshold", grayImg);
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
VectorOfRect hierarchy = new VectorOfRect();
CvInvoke.FindContours(grayImg, contours, hierarchy, RetrType.Tree, ChainApproxMethod.ChainApproxNone);
for(int i = 0; i < contours.Size; i++)
{
dst.SetTo(new MCvScalar(0, 0, 0));
maskImg.SetTo(new MCvScalar(0, 0, 0));
CvInvoke.DrawContours(maskImg, contours, i, new MCvScalar(255, 255, 255), -1);
double area = CvInvoke.ContourArea(contours[i], false);
if (area > 60) //简单的轮廓面积筛选
{
Mat mask = new Mat();
CvInvoke.CvtColor(maskImg, mask, ColorConversion.Bgr2Gray);
src.CopyTo(dst, mask);
CvInvoke.Imshow("mask", mask);
CvInvoke.Imshow("result", dst);
CvInvoke.WaitKey(0);
}
}
CvInvoke.WaitKey(0);
}
}
}
效果
1、最小外接圆,最小外接矩形:
2、轮廓提取