一、前文
基于边缘检测算法的轮廊寻找和提取
二、算法流程
- 高斯模糊
- Canny边缘检测
- FindContours寻找轮廓,轮廊提取
三、界面布局
- 一个
Label
- N个
Button
- 三个
Picture
四、功能实现
4.1 打开图片
private void openFileBtn_Click(object sender, EventArgs e)
{
OpenFileDialog openfiledialog = new OpenFileDialog();
openfiledialog.Filter = "PNG Files (*.png)|*.png|JPG Files (*.jpg)|*.jpg|GIF Files (*.gif)|*.gif";
openfiledialog.RestoreDirectory = true;
if (openfiledialog.ShowDialog() == DialogResult.OK)
{
Console.WriteLine(openfiledialog.FileName);
fileName = openfiledialog.FileName;
//Mat src = new Mat("foo.png", LoadMode.Color);
Mat src = new Mat(fileName);
//Mat src = new Mat(fileName, ImreadModes.Color);
var frameBitmap = BitmapConverter.ToBitmap(src);
pictureBox1.Image?.Dispose();
pictureBox1.Image = frameBitmap;
}
}
4.2 FindContours轮廓提取—源码
private void contoursBtn_Click(object sender, EventArgs e)
{
cannyBtn_Click(sender, e);
mOutput = new Mat(mInput.Rows, mInput.Cols, MatType.CV_8UC4);
mInput.CopyTo(mOutput);
RetrievalModes mode = RetrievalModes.External;
ContourApproximationModes method = ContourApproximationModes.ApproxNone;
Point offset = new OpenCvSharp.Point(0, 0);
Cv2.FindContours(
image: edges,
contours: out OpenCvSharp.Point[][] contours,
hierarchy: out HierarchyIndex[] outputArray,
mode: mode,
method: method,
offset: offset);
for (int i = 0; i < contours.Length; i++)
{
Scalar color = Scalar.RandomColor();
if (contours[i].Length > 100)
{
Cv2.DrawContours(
mOutput,
contours,
contourIdx: i,
color: color,
thickness: 2,
lineType: LineTypes.Link8,
hierarchy: outputArray,
maxLevel: 0);
}
}
srcPictureBox.Image = BitmapConverter.ToBitmap(mInput);
grayPictureBox.Image = BitmapConverter.ToBitmap(edges);
dstPictureBox.Image = BitmapConverter.ToBitmap(mOutput);
}
4.3 FindContours轮廓提取—参数讲解
//
// 摘要:
// Finds contours in a binary image.
//
// 参数:
// image:
// Source, an 8-bit single-channel image. Non-zero pixels are treated as 1’s. Zero
// pixels remain 0’s, so the image is treated as binary. The function modifies the
// image while extracting the contours.
//
// contours:
// Detected contours. Each contour is stored as a vector of points.
//
// hierarchy:
// Optional output vector, containing information about the image topology. It has
// as many elements as the number of contours. For each i-th contour contours[i],
// the members of the elements hierarchy[i] are set to 0-based indices in contours
// of the next and previous contours at the same hierarchical level, the first child
// contour and the parent contour, respectively. If for the contour i there are
// no next, previous, parent, or nested contours, the corresponding elements of
// hierarchy[i] will be negative.
//
// mode:
// Contour retrieval mode
//
// method:
// Contour approximation method
//
// offset:
// Optional offset by which every contour point is shifted. This is useful if the
// contours are extracted from the image ROI and then they should be analyzed in
// the whole image context.
public static void FindContours(InputArray image, out Point[][] contours, out HierarchyIndex[] hierarchy, RetrievalModes mode, ContourApproximationModes method, Point? offset = null);
image
,灰度图片输入contours
,轮廓结果输出mode
,轮廓检索模式External
,只检测外层轮廓List
,提取所有轮廓,并放置在list中,检测的轮廓不建立等级关系CComp
,提取所有轮廓,并将轮廓组织成双层结构(two-level hierarchy),顶层为连通域的外围边界,次层位内层边界Tree
,提取所有轮廓并重新建立网状轮廓结构FloodFill
,官网没有介绍,应该是洪水填充法
method
,轮廓近似方法ApproxNone
,获取每个轮廓的每个像素,相邻的两个点的像素位置差不超过1ApproxSimple
,压缩水平方向,垂直方向,对角线方向的元素,值保留该方向的重点坐标,如果一个矩形轮廓只需4个点来保存轮廓信息ApproxTC89L1
,使用Teh-Chinl链逼近算法中的一种ApproxTC89KCOS
,使用Teh-Chinl链逼近算法中的一种
五、运行效果图
从左到右
- 第一张是原图
- 第二张是高斯模糊的结果图
- 第三张是FindContours轮廊提取的结果图
六、参考
觉得好,就一键三连呗(点赞+收藏+关注)