21-22轮廓绘制(EmguCV学习)
注意
1、CvInvoke.FindContours()函数输入图像应该为二值图像,检测的轮廓针对的是白色物体(高亮部分);FindContours()函数会修改原图像;
2、hierarchy(层次结构) : 每个轮廓都有一个自己的层次结构;对每一个轮廓,hierarchy包含四个元素,表示同等级的后一个轮廓、前一个轮廓、子轮廓序号、父轮廓序号;在drawContours()函数中用的上,用来控制绘制的轮廓数;(参考:https://blog.csdn.net/qq_33810188/article/details/81285867?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task)
3、RetrType : 设置轮廓的检索模式(只检测最外层轮廓,检测全部轮廓,轮廓是否建立层级结构,轮廓建立2层层次结构) ; ChainApproxMethod : 轮廓近似方法(不近似保存所有点,近似只保存端点)
轮廓近似方法:
3、CvInvoke.DrawContours()函数:
contourIdx : 控制绘制当前轮廓i,如果为负值,则绘制所有轮廓;
thickness : 绘制线宽,如果为负,则填充轮廓;
hierarchy : 轮廓的层次结构信息;
maxLevel : 控制是否绘制当前轮廓之外的轮廓(需要有hierarchy信息做为参考):取0:只绘制当前轮廓,取1:绘制轮廓同一层次之后的所有轮廓;取2: 绘制轮廓之后所有轮廓,及轮廓之下所有子轮廓…
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 lesson21
{
class Program
{
static void Main(string[] args)
{
//Mat src = CvInvoke.Imread("01.png");
//Mat dst = src.Clone();
//Mat gray_src = new Mat();
//CvInvoke.Imshow("input", src);
//CvInvoke.CvtColor(src, gray_src, ColorConversion.Bgr2Gray);
//CvInvoke.Threshold(gray_src, gray_src, 100, 255, ThresholdType.Binary);
//VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
//VectorOfRect hierarchy = new VectorOfRect(); //等价vector<Vec4i>
//CvInvoke.FindContours(gray_src, contours, hierarchy, RetrType.Tree, ChainApproxMethod.ChainApproxSimple);
//Console.WriteLine("contours_size = {0}", contours.Size);
//CvInvoke.DrawContours(dst, contours, -1, new MCvScalar(0, 255, 0), 2,
// LineType.EightConnected,hierarchy); //maxLevel控制绘制轮廓数
//CvInvoke.Imshow("result", dst);
//CvInvoke.WaitKey(0);
//Mat src = CvInvoke.Imread("01.png");
//Mat dst = src.Clone();
//Mat gray_src = new Mat();
//CvInvoke.Imshow("input", src);
//CvInvoke.CvtColor(src, gray_src, ColorConversion.Bgr2Gray);
//CvInvoke.Threshold(gray_src, gray_src, 100, 255, ThresholdType.Binary);
//VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
//VectorOfRect hierarchy = new VectorOfRect(); //等价vector<Vec4i>
//CvInvoke.FindContours(gray_src, contours, hierarchy, RetrType.Tree, ChainApproxMethod.ChainApproxSimple);
//Console.WriteLine("contours_size = {0}", contours.Size);
//Random random = new Random();
遍历每一个轮廓
//for(int i = 0; i < contours.Size;i++)
//{
// CvInvoke.DrawContours(src, contours, i, new MCvScalar(random.Next(0, 255), random.Next(0, 255), random.Next(0, 255))
// , 2, LineType.EightConnected, hierarchy,0 );
// CvInvoke.Imshow("result1", src);
// CvInvoke.WaitKey(0);
//}
//遍历每个轮廓上的点
//for(int i = 0; i < contours.Size;i++)
//{
// for(int j = 0; j < contours[i].Size;j++)
// {
// CvInvoke.Circle(src, new Point(contours[i][j].X, contours[i][j].Y),
// 3, new MCvScalar(255, 0, 0), 2); //依次绘制所有轮廓点
// CvInvoke.Imshow("result", src); //每绘制一次显示显示一次
// CvInvoke.WaitKey(0);
// }
//}
//CvInvoke.WaitKey(0);
Mat src = CvInvoke.Imread("05.png");
Mat dst = src.Clone();
Mat gray_src = new Mat();
CvInvoke.Imshow("input", src);
CvInvoke.CvtColor(src, gray_src, ColorConversion.Bgr2Gray);
CvInvoke.Threshold(gray_src, gray_src, 100, 255, ThresholdType.BinaryInv);
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
VectorOfRect hierarchy = new VectorOfRect(); //等价vector<Vec4i>
CvInvoke.FindContours(gray_src, contours, hierarchy, RetrType.Tree, ChainApproxMethod.ChainApproxSimple);
Console.WriteLine("contours_size = {0}", contours.Size);
for(int i = 0; i< contours.Size;i++)
{
CvInvoke.DrawContours(src, contours, i, new MCvScalar(255, 0, 0), -1);
CvInvoke.Imshow("contours", src);
CvInvoke.WaitKey(0);
}
}
}
}
效果
1、绘制所有轮廓:
2、只保存轮廓端点:
3、每次只绘制一个轮廓(maxLevel = 0),遍历绘制所有轮廓:
4、轮廓填充: