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. js es6 介绍set,WeakSet

    前言 介绍一下es6 的set 和 weakset 正文 set ES6 提供了新的数据结构 Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. Set 本身是一个构造函数,用来生成 Set ...

  2. Web自动化实战:去哪儿网购票流程测试

    克隆源码 项目Github地址:https://github.com/gy-7/Web-automation-practice/tree/main/project1_qunar_booking_tic ...

  3. 算是不常用的东西,java中的ResultSet转List

    import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import j ...

  4. Vue 路由组件传参的 8 种方式

    我们在开发单页面应用时,有时需要进入某个路由后基于参数从服务器获取数据,那么我们首先要获取路由传递过来的参数,从而完成服务器请求,所以,我们需要了解路由传参的几种方式,以下方式同 vue-router ...

  5. 牛客网-SQL专项训练10

    ①SQL语句中与Having子句同时使用的语句是:group by 解析: SQL语法中,having需要与group by联用,起到过滤group by后数据的作用. ②下列说法错误的是?C 解析: ...

  6. Flink 作为现代数据仓库的统一引擎:Hive 集成生产就绪!

    在2020年,你的数据仓库和基础设施需要满足哪些需求? 我们总结了几下几点: 首先,当下的企业正快速转向更实时化的模式,这要求企业具备对线上流式数据进行低延迟处理的能力,以满足实时(real-time ...

  7. Dubbo-go 服务代理模型

    ​简介:HSF 是阿里集团 RPC/服务治理 领域的标杆,Go 语言又因为其高并发,云原生的特性,拥有广阔的发展前景和实践场景,服务代理模型只是一种落地场景,除此之外,还有更多的应用场景值得我们在研发 ...

  8. [FAQ] 快速准备 windows 的 nodejs 开发环境

      下载 git 版本控制系统:https://pc.qq.com/search.html#!keyword=git 下载 TortoiseGit 客户端:https://pc.qq.com/sear ...

  9. [FAQ] panic: listen tcp :xxxx: bind: Only one usage of each socket address (protocol/network address/port) is normally permitted.

    在 Go 中运行服务之前的绑定端口这一步,如果端口号被占用了,那么会提示它只能使用一次. 换个端口号或者检查端口号的占用程序. Link:https://www.cnblogs.com/farwish ...

  10. Oracle "脑残" CBO 优化案例

    今天晚上下班回来才有空看群,群友发了一条很简单的慢SQL问怎么优化. 非常简单,我自己模拟的数据. 表结构: -- auto-generated definition CREATE TABLE HHH ...