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

发布时间:2026/6/23 16:10:55
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, IEnumerableIEnumerable, int, Scalar, int, LineTypes, IEnumerable?, int, Point?) 如何按轮廓层级绘制指定子树并说明 contourIdx 和 maxLevel 的配合方式。1. 函数名称带参数签名publicstaticvoidDrawContours(InputOutputArrayimage,IEnumerableIEnumerablePointcontours,intcontourIdx,Scalarcolor,intthickness1,LineTypeslineTypeLineTypes.Link8,IEnumerableHierarchyIndex?hierarchynull,intmaxLevelint.MaxValue,Point?offsetnull)2. 函数用途Cv2.DrawContours(...)用来在图像上绘制一个或多个轮廓的边界或者在thickness 0时直接填充轮廓区域。这个重载直接接收点集和层级信息最适合从“轮廓树”角度理解绘制范围。它常用于轮廓可视化。目标分组和子轮廓高亮。带孔区域的边界说明。从 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){c∣c∈subtree(contourIdx),depth(c)≤maxLevel}这个公式不是 OpenCV 的源码公式而是帮助初学者理解contourIdx和maxLevel的抽象方式。contourIdx负责选根maxLevel负责决定向下展开多少层。4. 函数原理说明这个函数会先读取轮廓集合再根据contourIdx选择从哪一个轮廓开始绘制。如果传入了层级信息maxLevel就会决定要不要继续画子轮廓、孙轮廓。OpenCV 官方文档明确说明thickness 0时绘制轮廓边界。thickness 0时填充轮廓内部。maxLevel只在存在层级信息时才有意义。offset会把所有绘制出来的轮廓一起平移。对初学者来说最重要的是理解DrawContours不是简单地“把数组画出来”它会根据层级关系决定究竟画哪一部分。5. 参数含义解析参数名类型必填含义imageInputOutputArray是要被绘制的图像contoursIEnumerableIEnumerable是每条轮廓的点集contourIdxint是要从哪条轮廓开始绘制负数表示全部绘制colorScalar是轮廓颜色thicknessint否线宽负数表示填充lineTypeLineTypes否线型默认Link8hierarchyIEnumerable?否轮廓层级信息maxLevelint否最大绘制层级默认int.MaxValueoffsetPoint?否所有轮廓的整体平移量补充说明hierarchy的每一项都对应一条轮廓。contourIdx0并不代表“全部轮廓”它只代表从第 1 条轮廓开始。maxLevel越大递归展开得越深。6. 应用场景列表场景名场景说明典型用途场景A轮廓树可视化只画一个轮廓及其子树层级教学场景B孔洞轮廓看外轮廓和内轮廓的关系掩膜处理场景C局部高亮只强调某个目标轮廓调试展示场景D结果标注给提取结果加颜色视觉分析7. 函数使用示例说明下面示例对应 WPF 场景 A。它用点集和层级信息绘制轮廓子树并展示contourIdx0和maxLevel2的效果。usingOpenCvSharp;internalstaticclassProgram{privatestaticvoidMain(){// 准备一组有父子关系的轮廓外轮廓、洞、洞中的小岛以及右侧独立轮廓。varcontoursnew[]{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),},};// 手工构造层级信息和上面的四条轮廓一一对应。varhierarchynew[]{newHierarchyIndex(3,-1,1,-1),newHierarchyIndex(-1,-1,2,0),newHierarchyIndex(-1,-1,-1,1),newHierarchyIndex(-1,0,-1,-1),};usingvarcanvasnewMat(260,400,MatType.CV_8UC3,Scalar.White);usingvartargetInputOutputArray.Create(canvas);// contourIdx0 表示从第 1 条轮廓开始maxLevel2 表示展开两层子轮廓。Cv2.DrawContours(target,contours,0,newScalar(53,114,223),3,LineTypes.AntiAlias,hierarchy,2,null);// 保存图片检查轮廓子树是否按预期绘制。Cv2.ImWrite(drawcontours-point-enumerable.png,canvas);}}8. 注意事项contourIdx小于 0 时会绘制所有轮廓。maxLevel只有在提供层级信息时才有效。thickness 0会触发填充模式。offset只是整体平移不会改变轮廓形状。9. 调优建议如果只想高亮某个轮廓家族优先控制contourIdx和maxLevel。想让子轮廓关系更清楚可以给不同层级使用不同颜色再叠加说明。如果要表达“里面还有洞”建议先画外轮廓再画内轮廓。教学时可以把轮廓编号写在边界附近帮助初学者对照数组顺序。10. 进阶扩展可以把FindContours的结果直接拿来做这个函数的输入。可以结合ContourArea、BoundingRect一起讲轮廓几何。可以用offset做拖拽式轮廓平移。可以用thickness-1配合层级信息做填充掩膜。11. 常见错误排查误以为contourIdx0会画全部轮廓。没有层级信息却期待maxLevel产生递归效果。把thickness 0和正数线宽混淆。忽略轮廓点顺序导致图形方向和层级理解混乱。相关链接WPF 教学控件Cv2DrawContoursControl.xaml.cs样例实现DrawContoursPointEnumerableSample.cs官方文档源码位置OpenCvSharp/Cv2/Cv2_imgproc.cs