1. 查找轮廓 FindContours

public static void FindContours(InputOutputArray image, //输入8-bit单通道的图片
                    out Mat[] contours, //一组数组,contours[i]是一条轮廓,而contours[i][j]是点
                    OutputArray hierarchy, //输出一个数组,表示轮廓的树结构,每个值都是四元数组
                    RetrievalModes mode, //轮廓提取方式
                    ContourApproximationModes method, //轮廓如何被表达
                    Point? offset = null); public static void FindContours(InputOutputArray image,
                    out Point[][] contours,
                    out HierarchyIndex[] hierarchy,
                    RetrievalModes mode,
                    ContourApproximationModes method,
                    Point? offset = null);

2. 绘制轮廓 DrawContours

public static void DrawContours(InputOutputArray image, 
                    IEnumerable<Mat> contours,
                    int contourIdx, //需要绘制的轮廓索引,若为负,绘制所有轮廓
                    Scalar color, //颜色
                    int thickness = 1, //线粗
                    LineTypes lineType = LineTypes.Link8, //四联通、八联通、AA线
                    Mat hierarchy = null,
                    int maxLevel = int.MaxValue,
                    Point? offset = null); 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);

示例:滑动条和找轮廓

代码:

using System;
using OpenCvSharp; namespace ConsoleApp2
{
class Program
{ static void Main(string[] args)
{
Mat g_gray = new Mat();
Mat g_binary = new Mat();
int g_thresh = 100;
void on_trackbar(int pos, object userdata)
{
Cv2.Threshold((Mat)userdata, g_binary, pos, 255, ThresholdTypes.BinaryInv);
Point[][] contours; HierarchyIndex[] hierarchy;
Cv2.FindContours(g_binary, out contours, out hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxSimple);
Mat mask = new Mat(g_binary.Rows, g_binary.Cols, MatType.CV_8UC1, new Scalar(0));
Cv2.DrawContours(mask, contours, -1, new Scalar(255));
Cv2.ImShow("Contours", mask);
}
g_gray = Cv2.ImRead("C:\\Users\\ATWER\\Desktop\\b.png",ImreadModes.Grayscale);
Cv2.ImShow("gray", g_gray);
CvTrackbar cvTrackbar = new CvTrackbar("Threshold", "gray", g_thresh, 255, on_trackbar,g_gray);
Cv2.ImShow("gray", g_gray);
Cv2.WaitKey(0);
}
}
}

3. 查找连通区域 ConnectedComponentsWithStats

示例:连通区域

using System;
using OpenCvSharp; namespace ConsoleApp2
{
class Program
{ static void Main(string[] args)
{ Mat img = Cv2.ImRead("C:\\Users\\ATWER\\Desktop\\c.png");
Mat labelMat = new Mat(); Mat stats = new Mat();
Mat centroids = new Mat();
Cv2.CvtColor(img, img, ColorConversionCodes.BGR2GRAY);
       Cv2.NamedWindow("img",WindowMode.Normal);
       Cv2.ImShow("img", img);
int num = Cv2.ConnectedComponentsWithStats(img, labelMat, stats, centroids, PixelConnectivity.Connectivity4);
Console.WriteLine(num.ToString()); for (int i = 0; i < num; i++)
{
double a = centroids.At<double>(i, 0);
double b = centroids.At<double>(i, 1);
Point point = new OpenCvSharp.Point(a, b);
Cv2.Circle(img, point, 2, new Scalar(0, 0, 255));
int x = stats.At<int>(i, 0);
int y = stats.At<int>(i, 1);
int width = stats.At<int>(i, 2);
int height = stats.At<int>(i, 3);
Rect rect = new Rect(x, y, width, height);
Cv2.Rectangle(img, rect, new Scalar(255));
}
Cv2.NamedWindow("绘制质心", WindowMode.Normal);
Cv2.ImShow("绘制质心", img);
Cv2.WaitKey(0);
}
}
}

4. 多边形逼近轮廓 ApproxPolyDP()

public static void ApproxPolyDP(InputArray curve, 
                    OutputArray approxCurve,
                    double epsilon,
                    bool closed);

示例:多边形逼近一个圆的外轮廓

代码:

using System;
using System.Numerics;
using OpenCvSharp;
namespace ConsoleApp10
{
class Program
{
static void Main(string[] args)
{
Mat img = new Mat();
Mat src = Cv2.ImRead("D:\\Backup\\桌面\\c.png");
        //预处理
Cv2.CvtColor(src, img, ColorConversionCodes.BGR2GRAY);
Cv2.BitwiseNot(img, img);
Cv2.Threshold(img, img, 128, 255, ThresholdTypes.Binary);
Cv2.ImShow("img", img);
        //查找轮廓
Mat[] contours;
Mat hierarchy = new Mat();
Cv2.FindContours(img,out contours, hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
Mat[] contours_poly = (Mat[])contours.Clone();
//Cv2.DrawContours(img, contours, -1, new Scalar(255),5);
for (int i = 0; i < contours.Length; i++)
{
Cv2.ApproxPolyDP(contours[i], contours_poly[i], 10, true);//多边形逼近
}
        //绘制轮廓
Cv2.DrawContours(src, contours_poly, -1, new Scalar(0,255, 0),2);
Cv2.ImShow("a", src);
Cv2.WaitKey(0);
}
}
}

5. 获得矩形包围框 BoundingRect

public static Rect BoundingRect(InputArray curve);
public static RotatedRect MinAreaRect(InputArray points);

示例:矩形包围框

代码:

using System;
using System.Numerics;
using OpenCvSharp;
namespace ConsoleApp10
{
class Program
{
static void Main(string[] args)
{
Mat img = new Mat();
Mat src = Cv2.ImRead("D:\\Backup\\桌面\\c.png");
Cv2.ImShow("src", src);
Cv2.CvtColor(src, img, ColorConversionCodes.BGR2GRAY);
Cv2.BitwiseNot(img, img);
Cv2.Threshold(img, img, 128, 255, ThresholdTypes.Binary);
Cv2.ImShow("img", img);
//查找轮廓
       Mat[] contours;
Mat hierarchy = new Mat();
Cv2.FindContours(img,out contours, hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxSimple);
Mat[] contours_poly = (Mat[])contours.Clone();
for (int i = 0; i < contours.Length; i++)
{
Cv2.ApproxPolyDP(contours[i], contours_poly[i], 10, true);
//获得轮廓长度
double len = Cv2.ArcLength(contours_poly[i], true);
Console.WriteLine(len.ToString());
//获得矩形包围框
Rect rect = Cv2.BoundingRect(contours_poly[i]);
Cv2.Rectangle(src, rect, new Scalar(0),5);
//获得最小矩形框
RotatedRect rect_rotate = Cv2.MinAreaRect(contours_poly[i]);
Console.WriteLine(rect_rotate.Angle.ToString());
}
        //绘制轮廓
Cv2.DrawContours(src, contours_poly, -1, new Scalar(0,255, 0),2); Cv2.ImShow("a", src);
Cv2.WaitKey(0);
}
}

6. 获得轮廓凸包 ConvexHull

public static void ConvexHull(InputArray points, 
                  OutputArray hull,
                  bool clockwise = false,
                  bool returnPoints = true);

示例:轮廓凸包

代码:

using System;
using System.Numerics;
using OpenCvSharp;
namespace ConsoleApp10
{
class Program
{
static void Main(string[] args)
{
Mat img = new Mat();
Mat src = Cv2.ImRead("D:\\Backup\\桌面\\d.png");
Cv2.ImShow("src", src);
Cv2.CvtColor(src, img, ColorConversionCodes.BGR2GRAY);
Cv2.BitwiseNot(img, img);
Cv2.Threshold(img, img, 128, 255, ThresholdTypes.Binary);
Cv2.ImShow("img", img);
        //查找轮廓
Mat[] contours;
Mat hierarchy = new Mat();
Cv2.FindContours(img,out contours, hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxSimple);
        //凸包 居然想不到第二个方法把hulls画出来
Mat hulls = new Mat();
Cv2.ConvexHull(contours[0],hulls,false);
Mat[] r = new Mat[] { hulls };
        //绘制轮廓
Cv2.DrawContours(src, r, -1, new Scalar(0, 255, 0), 2);
Cv2.ImShow("a", src);
Cv2.WaitKey(0);
}
}
}

7. Tips

学到一个新知识点,在二值化和查找轮廓之间,运用开运算,可以去除小的区域干扰。相比于在for循环遍历中再判断大小,要更节约时间。——2021.10.18

源自:蝴蝶书第十四章轮廓

OpenCV笔记(7) 轮廓的更多相关文章

  1. OpenCV笔记大集锦(转载)

    整理了我所了解的有关OpenCV的学习笔记.原理分析.使用例程等相关的博文.排序不分先后,随机整理的.如果有好的资源,也欢迎介绍和分享. 1:OpenCV学习笔记 作者:CSDN数量:55篇博文网址: ...

  2. opencv笔记6:角点检测

    time:2015年10月09日 星期五 23时11分58秒 # opencv笔记6:角点检测 update:从角点检测,学习图像的特征,这是后续图像跟踪.图像匹配的基础. 角点检测是什么鬼?前面一篇 ...

  3. opencv笔记5:频域和空域的一点理解

    time:2015年10月06日 星期二 12时14分51秒 # opencv笔记5:频域和空域的一点理解 空间域和频率域 傅立叶变换是f(t)乘以正弦项的展开,正弦项的频率由u(其实是miu)的值决 ...

  4. opencv笔记4:模板运算和常见滤波操作

    time:2015年10月04日 星期日 00时00分27秒 # opencv笔记4:模板运算和常见滤波操作 这一篇主要是学习模板运算,了解各种模板运算的运算过程和分类,理论方面主要参考<图像工 ...

  5. opencv笔记3:trackbar简单使用

    time:2015年 10月 03日 星期六 13:54:17 CST # opencv笔记3:trackbar简单使用 当需要测试某变量的一系列取值取值会产生什么结果时,适合用trackbar.看起 ...

  6. opencv笔记2:图像ROI

    time:2015年 10月 03日 星期六 12:03:45 CST # opencv笔记2:图像ROI ROI ROI意思是Region Of Interests,感兴趣区域,是一个图中的一个子区 ...

  7. opencv笔记1:opencv的基本模块,以及环境搭建

    opencv笔记1:opencv的基本模块,以及环境搭建 安装系统 使用fedora22-workstation-x86_64 安装opencv sudo dnf install opencv-dev ...

  8. [OpenCV-Python] 21 OpenCV 中的轮廓

    文章目录 OpenCV-Python:IV OpenCV中的图像处理 21 OpenCV 中的轮廓 21.1 初识轮廓 21.1.1 什么是轮廓 21.1.2 怎样绘制轮廓 21.1.3 轮廓的近似方 ...

  9. 查找并绘制轮廓[OpenCV 笔记XX]

    好久没有更新了,原谅自己放了个假最近又在赶进度,所以...更新的内容是很靠后的第八章,因为最近工作要用就先跳了,后面会更新笔记编号...加油加油! 在二值图像中寻找轮廓 void cv::findCo ...

  10. OpenCV学习笔记(12)——OpenCV中的轮廓

    什么是轮廓 找轮廓.绘制轮廓等 1.什么是轮廓 轮廓可看做将连续的点(连着边界)连在一起的曲线,具有相同的颜色和灰度.轮廓在形态分析和物体的检测和识别中很有用. 为了更加准确,要使用二值化图像.在寻找 ...

随机推荐

  1. MMDeploy部署实战系列【第五章】:Windows下Release x64编译mmdeploy(C++),对TensorRT模型进行推理

    MMDeploy部署实战系列[第五章]:Windows下Release x64编译mmdeploy(C++),对TensorRT模型进行推理 这个系列是一个随笔,是我走过的一些路,有些地方可能不太完善 ...

  2. Ajax 原理是什么?如何实现?

    一.是什么 AJAX全称(Asynchronous Javascript And XML) 即异步的JavaScript 和XML,是一种创建交互式网页应用的网页开发技术,可以在不重新加载整个网页的情 ...

  3. sql多表分页查询【oracle】

    sql多表查询[oracle] 做个记录,好歹是写出来了,使用左连接的方法,进行四表查询,且使用rownum进行分页 把涉及内容的全部替换了,不过应该都看得懂,就不说了 select * from ( ...

  4. 力扣28(java)-实现 strStr()(简单)

    题目: 实现 strStr() 函数. 给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始).如果不存 ...

  5. 力扣233(java)-数字1的个数(困难)

    题目: 给定一个整数 n,计算所有小于等于 n 的非负整数中数字 1 出现的个数. 示例 1: 输入:n = 13输出:6示例 2: 输入:n = 0输出:0 提示: 0 <= n <= ...

  6. 云原生数据仓库AnalyticDB支撑双11,大幅提升分析实时性和用户体验

    ​简介:2021年双十一刚刚落幕,已连续多年稳定支持双十一大促的云原生数据仓库AnalyticDB,今年双十一期间仍然一如既往的稳定.除了稳定顺滑的基本盘之外,AnalyticDB还有什么亮点呢?下面 ...

  7. 干货|一文读懂阿里云数据库Autoscaling是如何工作的

    简介: 阿里云数据库实现了其特有的Autosaling能力,该能力由数据库内核.管控及DAS(数据库自治服务)团队共同构建,内核及管控团队提供了数据库Autoscaling的基础能力,DAS则负责性能 ...

  8. [GPT] 监测输入框被 js 设置了值 ?input 输入框被设置了 value 值,但是没有触发 change 事件?

    1. input 输入框被设置了 value 值,但是没有触发 change 事件 ? 如果输入框的 value 值是通过 JavaScript 代码直接设置的,那么不会触发 change 事件,这是 ...

  9. [Ethereum] Gas Station Network (GSN) eip-1613 与 Gas Relay Network (GRN) eip-1077

    在 Ethereum dapp 中,任何涉及状态改动的交易都需要消耗 Gas,这限制了很多没有钱包或者 ETH 的用户对 dapp 的采用. 理念 让非以太用户能够访问智能合约 (如dapps),允许 ...

  10. 笔记06-第六讲 Cadence同一页面建立电气互连

    笔记06-第六讲 Cadence同一页面建立电气互连 内容: 90度和任意角度连线; 连线方式; 十字线添加/删除连接点; Net alias; 无连接的管脚处理; 注意事项. 连线有两种方式,右侧工 ...