news 2026/6/23 16:10:27

OpencvSharp 算子学习教案之 - Cv2.DrawContours 重载1

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OpencvSharp 算子学习教案之 - Cv2.DrawContours 重载1

OpencvSharp 算子学习教案之 - Cv2.DrawContours 重载1

大家好,Opencv在很多工程项目中都会用到,而OpencvSharp则是以C#开发与实现的Opencv操作库,对.NET开发人员友好,但很多API的中文资料、应用场景及常见坑点等缺乏系统性归纳,因此这系列博客将给大家带来Cv2及Mat对象全系列算子学习教案,供大家参考学习。

Cv2.DrawContours

  • 教案版本:V1.0
  • 面向对象:OpenCvSharp 初学者
  • 所属模块:imgproc
  • 源码位置:OpenCvSharp/Cv2/Cv2_imgproc.cs:4864

摘要:本页演示 DrawContours(InputOutputArray, IEnumerable<IEnumerable>, int, Scalar, int, LineTypes, IEnumerable?, int, Point?) 如何按轮廓层级绘制指定子树,并说明 contourIdx 和 maxLevel 的配合方式。

1. 函数名称(带参数签名)

publicstaticvoidDrawContours(InputOutputArrayimage,IEnumerable<IEnumerable<Point>>contours,intcontourIdx,Scalarcolor,intthickness=1,LineTypeslineType=LineTypes.Link8,IEnumerable<HierarchyIndex>?hierarchy=null,intmaxLevel=int.MaxValue,Point?offset=null)

2. 函数用途

Cv2.DrawContours(...)用来在图像上绘制一个或多个轮廓的边界,或者在thickness < 0时直接填充轮廓区域。这个重载直接接收点集和层级信息,最适合从“轮廓树”角度理解绘制范围。

它常用于:

  1. 轮廓可视化。
  2. 目标分组和子轮廓高亮。
  3. 带孔区域的边界说明。
  4. 从 FindContours 的结果里筛选某个轮廓子树。

3. 函数公式

如果把轮廓看成有父子关系的树,那么绘制范围可以理解成:

S ( contourIdx , maxLevel ) = { c ∣ c ∈ subtree ( contourIdx ) , depth ( c ) ≤ maxLevel } S(\text{contourIdx},\text{maxLevel})=\{c\mid c\in \text{subtree}(\text{contourIdx}),\;\text{depth}(c)\le \text{maxLevel}\}S(contourIdx,maxLevel)={ccsubtree(contourIdx),depth(c)maxLevel}

这个公式不是 OpenCV 的源码公式,而是帮助初学者理解contourIdxmaxLevel的抽象方式。contourIdx负责选根,maxLevel负责决定向下展开多少层。

4. 函数原理说明

这个函数会先读取轮廓集合,再根据contourIdx选择从哪一个轮廓开始绘制。如果传入了层级信息,maxLevel就会决定要不要继续画子轮廓、孙轮廓。

OpenCV 官方文档明确说明:

  1. thickness >= 0时绘制轮廓边界。
  2. thickness < 0时填充轮廓内部。
  3. maxLevel只在存在层级信息时才有意义。
  4. offset会把所有绘制出来的轮廓一起平移。

对初学者来说,最重要的是理解:DrawContours不是简单地“把数组画出来”,它会根据层级关系决定究竟画哪一部分。

5. 参数含义解析

参数名类型必填含义
imageInputOutputArray要被绘制的图像
contoursIEnumerable<IEnumerable>每条轮廓的点集
contourIdxint要从哪条轮廓开始绘制,负数表示全部绘制
colorScalar轮廓颜色
thicknessint线宽,负数表示填充
lineTypeLineTypes线型,默认Link8
hierarchyIEnumerable?轮廓层级信息
maxLevelint最大绘制层级,默认int.MaxValue
offsetPoint?所有轮廓的整体平移量

补充说明:

  1. hierarchy的每一项都对应一条轮廓。
  2. contourIdx=0并不代表“全部轮廓”,它只代表从第 1 条轮廓开始。
  3. maxLevel越大,递归展开得越深。

6. 应用场景列表

场景名场景说明典型用途
场景A:轮廓树可视化只画一个轮廓及其子树层级教学
场景B:孔洞轮廓看外轮廓和内轮廓的关系掩膜处理
场景C:局部高亮只强调某个目标轮廓调试展示
场景D:结果标注给提取结果加颜色视觉分析

7. 函数使用示例

说明:下面示例对应 WPF 场景 A。它用点集和层级信息绘制轮廓子树,并展示contourIdx=0maxLevel=2的效果。

usingOpenCvSharp;internalstaticclassProgram{privatestaticvoidMain(){// 准备一组有父子关系的轮廓:外轮廓、洞、洞中的小岛,以及右侧独立轮廓。varcontours=new[]{new[]{newPoint(52,50),newPoint(158,40),newPoint(196,98),newPoint(170,174),newPoint(88,186),newPoint(42,122),},new[]{newPoint(88,82),newPoint(138,78),newPoint(154,118),newPoint(126,144),newPoint(82,124),},new[]{newPoint(108,98),newPoint(126,94),newPoint(132,114),newPoint(112,122),},new[]{newPoint(244,62),newPoint(312,46),newPoint(346,94),newPoint(328,156),newPoint(260,146),newPoint(232,100),},};// 手工构造层级信息,和上面的四条轮廓一一对应。varhierarchy=new[]{newHierarchyIndex(3,-1,1,-1),newHierarchyIndex(-1,-1,2,0),newHierarchyIndex(-1,-1,-1,1),newHierarchyIndex(-1,0,-1,-1),};usingvarcanvas=newMat(260,400,MatType.CV_8UC3,Scalar.White);usingvartarget=InputOutputArray.Create(canvas);// contourIdx=0 表示从第 1 条轮廓开始,maxLevel=2 表示展开两层子轮廓。Cv2.DrawContours(target,contours,0,newScalar(53,114,223),3,LineTypes.AntiAlias,hierarchy,2,null);// 保存图片,检查轮廓子树是否按预期绘制。Cv2.ImWrite("drawcontours-point-enumerable.png",canvas);}}

8. 注意事项

  1. contourIdx小于 0 时会绘制所有轮廓。
  2. maxLevel只有在提供层级信息时才有效。
  3. thickness < 0会触发填充模式。
  4. offset只是整体平移,不会改变轮廓形状。

9. 调优建议

  1. 如果只想高亮某个轮廓家族,优先控制contourIdxmaxLevel
  2. 想让子轮廓关系更清楚,可以给不同层级使用不同颜色再叠加说明。
  3. 如果要表达“里面还有洞”,建议先画外轮廓再画内轮廓。
  4. 教学时可以把轮廓编号写在边界附近,帮助初学者对照数组顺序。

10. 进阶扩展

  1. 可以把FindContours的结果直接拿来做这个函数的输入。
  2. 可以结合ContourAreaBoundingRect一起讲轮廓几何。
  3. 可以用offset做拖拽式轮廓平移。
  4. 可以用thickness=-1配合层级信息做填充掩膜。

11. 常见错误排查

  1. 误以为contourIdx=0会画全部轮廓。
  2. 没有层级信息却期待maxLevel产生递归效果。
  3. thickness < 0和正数线宽混淆。
  4. 忽略轮廓点顺序,导致图形方向和层级理解混乱。

相关链接:

  • WPF 教学控件:Cv2DrawContoursControl.xaml.cs
  • 样例实现:DrawContoursPointEnumerableSample.cs
  • 官方文档源码位置:OpenCvSharp/Cv2/Cv2_imgproc.cs
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/23 16:08:24

电阻、电容、电感,二极管、三极管、mos管

一、电阻1、核心定义&#xff1a;电阻是消耗电能&#xff0c;将电能转化为热能的元件&#xff0c;是纯耗能元件2、单位&#xff1a;欧姆Ω3、作用&#xff1a;限流、分压、发热&#xff08;WI^2*R&#xff09;&#xff0c;匹配阻抗、构成滤波器4、核心定律&#xff1a;欧姆定律…

作者头像 李华
网站建设 2026/6/23 16:06:11

(一)站稳脚:用Scikit-learn跑通第一条Pipeline

从CSV到模型&#xff0c;一个完整的ML项目长什么样 你装好了Python&#xff0c;跑通了Ollama&#xff0c;手上有一本《动手学深度学习》的克隆。但你可能还在想一个问题&#xff1a;机器学习项目&#xff0c;到底是怎么从零跑到尾的&#xff1f; 网上有大量教程教你怎么调 fit…

作者头像 李华
网站建设 2026/6/23 16:00:12

软件|Navicat Premium16 免费安装配置教程(附安装包)

一、下载安装包官网下载&#xff1a;https://www.navicat.com.cn/products#navicat可直接网盘下载链接 &#xff1a;https://pan.baidu.com/s/1Y_9TzouLX7AtgEww_yVYaQ?pwdsili 如失效后台发送&#xff3b;四里&#xff3d;&#xff0c;重新获取二、安装过程1. 双击安装包2. 选…

作者头像 李华
网站建设 2026/6/23 15:56:15

山东大学项目实训6月20日

在项目中&#xff0c;我主要负责代码审查链路中的代码分析和静态扫描&#xff0c;具体包括以下几个方面&#xff1a;1. 静态分析与结构上下文构建负责将 PR 变更代码、Semgrep 扫描结果和 Tree-sitter 解析结果进行统一组织&#xff0c;形成可用于后续审查的结构化证据输入。 这…

作者头像 李华
网站建设 2026/6/23 15:41:35

基于神经元激活图的目标导向预训练数据选择:原理、实现与实战

1. 项目概述&#xff1a;从“大锅饭”到“精准投喂”的数据选择革命 在深度学习模型训练&#xff0c;尤其是预训练阶段&#xff0c;我们常常面临一个看似简单却极其关键的抉择&#xff1a;用哪些数据&#xff1f;过去很长一段时间&#xff0c;业界的主流做法是“大力出奇迹”—…

作者头像 李华
网站建设 2026/6/23 15:27:31

Ubuntu 12.04 部署 CouchDB 1.6.1 与 Futon 实战指南

1. 项目概述&#xff1a;为什么在 Ubuntu 12.04 上部署 CouchDB Futon 仍值得深挖 CouchDB 是一个以 JSON 为数据模型、HTTP 为 API 协议、MapReduce 为查询引擎的面向文档型数据库&#xff0c;它的设计哲学是“最终一致性”与“离线优先”&#xff0c;这在移动端同步、边缘计…

作者头像 李华