注意
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、輪廓填充: