实现流程:
- 边缘查找
- 轮廓发现
- 绘制轮廓
API:
- 查找轮廓
public static void FindContours(InputArray image, out Point[][] contours, out HierarchyIndex[] hierarchy, RetrievalModes mode, ContourApproximationModes method, Point? offset = null);
参数
image | 输入图像,灰度图 |
---|---|
contours | 轮廓输出结果 |
hierarchy | 可选输出向量,包含关于图像拓扑的信息 |
mode | 轮廓检索模式 |
method | 轮廓近似方法 |
offset | 可选参数,偏移量,如(-10,10)表示轮廓点沿X负方向偏移10个像素点,沿Y正方向偏移10个像素点 |
轮廓检索模式:
- RetrievalModes.EXTERNAL - 只提取最外层的轮廓
- RetrievalModes.LIST - 提取所有轮廓,并且放置在 list 中
- RetrievalModes.CCOMP - 提取所有轮廓,并且将其组织为两层的 hierarchy: 顶层为连通域的外围边界,次层为洞的内层边界。
- RetrievalModes.TREE - 提取所有轮廓,并且重构嵌套轮廓的全部 hierarchy
轮廓近似方法:
- ContourApproximationModes.ApproxNone - 将所有点由链码形式翻译(转化)为点序列形式
- ContourApproximationModes.ApproxSimple - 压缩水平、垂直和对角分割,即函数只保留末端的象素点;
- ContourApproximationModes.ApproxTC89L1/ContourApproximationModes.ApproxTC89KCOS - 应用 Teh-Chin 链逼近算法. CV_LINK_RUNS - 通过连接为 1 的水平碎片使用完全不同的轮廓提取算法。仅有 CV_RETR_LIST 提取模式可以在本方法中应用.
- 绘制轮廓
public static void DrawContours(InputOutputArray image, IEnumerable<IEnumerable<Point>> contours, int contourIdx, Scalar color, int thickness = 1, LineTypes lineType = LineTypes.Link8, IEnumerable<HierarchyIndex>? hierarchy = null, int maxLevel = int.MaxValue, Point? offset = null);
参数
image | 输入图像 |
---|---|
contours | 轮廓输出结果 |
contourIdx | 轮廓编号 |
color | 轮廓颜色 |
thickness | 线宽 |
lineType | 线型 |
hierarchy | 关于轮廓图像拓扑的信息 |
maxLevel | 绘制轮廓的最大等级 |
代码演示
private string picFile = "";
private Mat inputMat;
private Mat outMat;
private Mat displayMat;
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog fileDialog = new OpenFileDialog();
if (fileDialog.ShowDialog() == DialogResult.OK)
{
picFile = fileDialog.FileName;
inputMat = Cv2.ImRead(picFile, ImreadModes.Grayscale);
displayMat = Cv2.ImRead(picFile, ImreadModes.AnyColor);
outMat = new Mat(new Size(inputMat.Cols, inputMat.Rows), inputMat.Type());
Cv2.Canny(inputMat, outMat, 30, 90);
//仅查找外轮廓
Cv2.FindContours(outMat, out OpenCvSharp.Point[][] contours,out HierarchyIndex[] outputArray, RetrievalModes.External,ContourApproximationModes.ApproxNone);
//绘制轮廓
Scalar color = new Scalar(255, 0, 0);
for (int i = 0; i < contours.Length; i++)
{
if (contours[i].Length > 100)
{
Cv2.DrawContours(displayMat,contours, i,color,5,LineTypes.Link8, outputArray, 0);
}
}
picBox_Display.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(inputMat);
picBox_After.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(displayMat);
}
}
绘制所有轮廓
仅绘制外轮廓
补充说明:
本案例在.NET使用的OpenCV库为OpenCvSharp4